From 7b2ffa587235a47d4094787d72f38102089f402a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 31 Jul 2019 15:50:41 +0200 Subject: BASELINE: Update Chromium to 76.0.3809.94 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647 Reviewed-by: Michael Brüning --- .../third_party/blink/renderer/devtools/BUILD.gn | 16 +- .../third_party/blink/renderer/devtools/OWNERS | 1 + .../blink/renderer/devtools/PRESUBMIT.py | 44 +- .../devtools/front_end/Images/mediumIcons.png | Bin 4442 -> 4912 bytes .../devtools/front_end/Images/mediumIcons_2x.png | Bin 9703 -> 10703 bytes .../devtools/front_end/Images/src/mediumIcons.svg | 308 +- .../front_end/Images/src/optimize_png.hashes | 2 +- .../devtools/front_end/Images/src/svg2png.hashes | 2 +- .../devtools/front_end/Images/whatsnew.png | Bin 12180 -> 12134 bytes .../blink/renderer/devtools/front_end/Runtime.js | 19 +- .../blink/renderer/devtools/front_end/Tests.js | 110 + .../front_end/accessibility/accessibilityNode.css | 13 - .../accessibility/accessibility_strings.grdp | 90 + .../front_end/animation/animationTimeline.css | 13 - .../front_end/animation/animation_strings.grdp | 39 + .../front_end/audits2/Audits2Controller.js | 34 +- .../devtools/front_end/audits2/Audits2Panel.js | 16 +- .../front_end/audits2/Audits2ReportRenderer.js | 8 + .../devtools/front_end/audits2/Audits2StartView.js | 13 +- .../front_end/audits2/Audits2StatusView.js | 4 +- .../devtools/front_end/audits2/audits2Dialog.css | 5 - .../devtools/front_end/audits2/audits2Panel.css | 55 - .../front_end/audits2/audits2_strings.grdp | 148 + .../front_end/audits2/lighthouse/report.css | 897 ++-- .../front_end/audits2/lighthouse/report.js | 1130 ++++- .../front_end/audits2/lighthouse/templates.html | 635 ++- .../lighthouse/lighthouse-dt-bundle.js | 4662 +++++++++++++------- .../front_end/bindings/bindings_strings.grdp | 9 + .../browser_debugger/browser_debugger_strings.grdp | 66 + .../front_end/browser_sdk/browser_sdk_strings.grdp | 15 + .../front_end/changes/changes_strings.grdp | 36 + .../color_picker/color_picker_strings.grdp | 51 + .../devtools/front_end/color_picker/spectrum.css | 41 +- .../renderer/devtools/front_end/common/UIString.js | 15 +- .../devtools/front_end/components/Linkifier.js | 1 + .../front_end/components/components_strings.grdp | 54 + .../devtools/front_end/console/ConsoleView.js | 52 +- .../devtools/front_end/console/consoleSidebar.css | 4 - .../front_end/console/console_strings.grdp | 294 ++ .../devtools/front_end/console/module.json | 18 + .../console_counters/console_counters_strings.grdp | 21 + .../front_end/cookie_table/CookiesTable.js | 35 +- .../cookie_table/cookie_table_strings.grdp | 33 + .../front_end/coverage/coverage_strings.grdp | 61 + .../front_end/data_grid/data_grid_strings.grdp | 21 + .../devtools/front_end/devices/DevicesView.js | 5 +- .../devtools/front_end/devices/devicesView.css | 7 - .../front_end/devices/devices_strings.grdp | 111 + .../renderer/devtools/front_end/devtools_app.json | 3 +- .../devtools/front_end/devtools_compatibility.js | 8 + .../front_end/elements/ElementsTreeElement.js | 3 +- .../front_end/elements/ElementsTreeOutline.js | 2 + .../front_end/elements/EventListenersWidget.js | 1 + .../front_end/elements/StylePropertyTreeElement.js | 117 +- .../front_end/elements/StylesSidebarPane.js | 54 +- .../front_end/elements/elementsTreeOutline.css | 5 +- .../front_end/elements/elements_strings.grdp | 327 ++ .../elements_test_runner/ElementsTestRunner.js | 18 +- .../emulated_devices/emulated_devices_strings.grdp | 102 + .../devtools/front_end/emulation/SensorsView.js | 3 +- .../front_end/emulation/devicesSettingsTab.css | 6 - .../front_end/emulation/emulation_strings.grdp | 279 ++ .../emulation/geolocationsSettingsTab.css | 6 - .../devtools/front_end/emulation/sensors.css | 12 - .../event_listeners/event_listeners_strings.grdp | 18 + .../blink/renderer/devtools/front_end/externs.js | 18 + .../devtools/front_end/har_importer/HARFormat.js | 24 + .../devtools/front_end/har_importer/HARImporter.js | 18 + .../heap_snapshot_worker_strings.grdp | 27 + .../devtools/front_end/help/ReleaseNoteText.js | 23 + .../devtools/front_end/help/help_strings.grdp | 21 + .../front_end/host/InspectorFrontendHost.js | 7 + .../front_end/host/InspectorFrontendHostAPI.js | 5 + .../renderer/devtools/front_end/host/Platform.js | 2 +- .../devtools/front_end/host/host_strings.grdp | 6 + .../front_end/inline_editor/bezierEditor.css | 4 - .../inline_editor/inline_editor_strings.grdp | 24 + .../inspector_main/inspector_main_strings.grdp | 96 + .../front_end/js_profiler/js_profiler_strings.grdp | 6 + .../front_end/langpacks/devtools_ui_strings.grd | 72 + .../front_end/layer_viewer/PaintProfilerView.js | 3 +- .../layer_viewer/layer_viewer_strings.grdp | 213 + .../front_end/layer_viewer/paintProfiler.css | 6 - .../devtools/front_end/layers/layers_strings.grdp | 9 + .../blink/renderer/devtools/front_end/main/Main.js | 5 +- .../devtools/front_end/main/main_strings.grdp | 129 + .../mobile_throttling_strings.grdp | 108 + .../front_end/network/NetworkDataGridNode.js | 4 + .../devtools/front_end/network/NetworkLogView.js | 31 +- .../devtools/front_end/network/NetworkPanel.js | 75 +- .../front_end/network/RequestHeadersView.js | 16 +- .../network/ResourceWebSocketFrameView.js | 11 +- .../front_end/network/networkConfigView.css | 4 +- .../devtools/front_end/network/networkLogView.css | 1 + .../devtools/front_end/network/networkPanel.css | 37 +- .../front_end/network/network_strings.grdp | 768 ++++ .../front_end/network/requestHeadersView.css | 8 - .../front_end/network/webSocketFrameView.css | 20 +- .../node_debugger/node_debugger_strings.grdp | 6 + .../front_end/node_main/NodeConnectionsPanel.js | 2 +- .../front_end/node_main/nodeConnectionsPanel.css | 11 - .../front_end/node_main/node_main_strings.grdp | 18 + .../devtools/front_end/object_ui/objectPopover.css | 6 - .../devtools/front_end/object_ui/objectValue.css | 6 - .../front_end/object_ui/object_ui_strings.grdp | 51 + .../devtools/front_end/perf_ui/PieChart.js | 67 +- .../devtools/front_end/perf_ui/filmStripView.css | 9 - .../front_end/perf_ui/perf_ui_strings.grdp | 60 + .../devtools/front_end/perf_ui/pieChart.css | 45 +- .../performance_monitor/PerformanceMonitor.js | 6 +- .../performance_monitor/performanceMonitor.css | 12 - .../performance_monitor_strings.grdp | 36 + .../TimelineDataTestRunner.js | 2 +- .../front_end/persistence/persistence_strings.grdp | 57 + .../product_registry/product_registry_strings.grdp | 12 + .../devtools/front_end/profiler/HeapProfileView.js | 3 +- .../front_end/profiler/HeapSnapshotView.js | 25 +- .../devtools/front_end/profiler/IsolateSelector.js | 75 +- .../front_end/profiler/LiveHeapProfileView.js | 78 +- .../front_end/profiler/ProfileLauncherView.js | 39 +- .../devtools/front_end/profiler/heapProfiler.css | 32 - .../front_end/profiler/profileLauncherView.css | 91 +- .../front_end/profiler/profiler_strings.grdp | 439 ++ .../devtools/front_end/profiler/profilesPanel.css | 89 - .../protocol_monitor/protocol_monitor_strings.grdp | 27 + .../front_end/quick_open/quick_open_strings.grdp | 21 + .../front_end/resources/AppManifestView.js | 7 +- .../front_end/resources/ApplicationPanelSidebar.js | 101 +- .../front_end/resources/BackgroundServiceView.js | 163 +- .../front_end/resources/ClearStorageView.js | 17 +- .../devtools/front_end/resources/ResourcesPanel.js | 15 +- .../front_end/resources/ResourcesSection.js | 2 +- .../front_end/resources/ServiceWorkersView.js | 73 +- .../front_end/resources/backgroundServiceView.css | 28 + .../front_end/resources/clearStorageView.css | 24 - .../front_end/resources/indexedDBViews.css | 9 - .../devtools/front_end/resources/module.json | 32 + .../front_end/resources/resourcesPanel.css | 35 - .../front_end/resources/resources_strings.grdp | 398 ++ .../resources/serviceWorkerCacheViews.css | 9 - .../front_end/resources/serviceWorkersView.css | 45 +- .../front_end/screencast/screencast_strings.grdp | 12 + .../renderer/devtools/front_end/sdk/CSSMetadata.js | 63 +- .../devtools/front_end/sdk/ChildTargetManager.js | 3 + .../devtools/front_end/sdk/ConsoleModel.js | 2 +- .../renderer/devtools/front_end/sdk/CookieModel.js | 5 +- .../renderer/devtools/front_end/sdk/DOMModel.js | 9 +- .../renderer/devtools/front_end/sdk/HARLog.js | 10 + .../devtools/front_end/sdk/IsolateManager.js | 18 +- .../devtools/front_end/sdk/NetworkManager.js | 37 +- .../devtools/front_end/sdk/NetworkRequest.js | 21 +- .../devtools/front_end/sdk/ResourceTreeModel.js | 8 + .../devtools/front_end/sdk/ScreenCaptureModel.js | 8 + .../devtools/front_end/sdk/sdk_strings.grdp | 303 ++ .../devtools/front_end/search/search_strings.grdp | 36 + .../devtools/front_end/security/SecurityModel.js | 7 +- .../devtools/front_end/security/SecurityPanel.js | 93 +- .../devtools/front_end/security/mainView.css | 12 - .../front_end/security/security_strings.grdp | 144 + .../security_test_runner/SecurityTestRunner.js | 12 +- .../settings/FrameworkBlackboxSettingsTab.js | 15 +- .../settings/frameworkBlackboxSettingsTab.css | 4 + .../devtools/front_end/settings/settingsScreen.css | 17 - .../front_end/settings/settings_strings.grdp | 54 + .../front_end/snippets/snippets_strings.grdp | 9 + .../devtools/front_end/source_frame/SourceFrame.js | 2 +- .../source_frame/source_frame_strings.grdp | 75 + .../front_end/sources/breakpointEditDialog.css | 5 - .../devtools/front_end/sources/module.json | 2 - .../devtools/front_end/sources/revisionHistory.css | 68 - .../front_end/sources/serviceWorkersSidebar.css | 9 - .../devtools/front_end/sources/sourcesPanel.css | 8 - .../devtools/front_end/sources/sourcesView.css | 5 - .../front_end/sources/sources_strings.grdp | 483 ++ .../front_end/terminal/terminal_strings.grdp | 9 + .../devtools/front_end/test_runner/TestRunner.js | 42 + .../front_end/text_editor/text_editor_strings.grdp | 6 + .../devtools/front_end/timeline/TimelineUIUtils.js | 15 +- .../devtools/front_end/timeline/timelinePanel.css | 87 - .../front_end/timeline/timeline_strings.grdp | 942 ++++ .../timeline_model/timeline_model_strings.grdp | 9 + .../renderer/devtools/front_end/ui/ARIAUtils.js | 26 + .../renderer/devtools/front_end/ui/EmptyWidget.js | 8 + .../blink/renderer/devtools/front_end/ui/Icon.js | 4 + .../renderer/devtools/front_end/ui/ReportView.js | 17 +- .../devtools/front_end/ui/ShortcutsScreen.js | 139 +- .../devtools/front_end/ui/SoftContextMenu.js | 11 +- .../renderer/devtools/front_end/ui/SoftDropDown.js | 13 +- .../renderer/devtools/front_end/ui/SuggestBox.js | 3 +- .../renderer/devtools/front_end/ui/TextPrompt.js | 8 +- .../renderer/devtools/front_end/ui/Tooltip.js | 9 +- .../renderer/devtools/front_end/ui/filter.css | 20 - .../devtools/front_end/ui/inspectorCommon.css | 15 +- .../front_end/ui/inspectorSyntaxHighlight.css | 6 - .../front_end/ui/inspectorSyntaxHighlightDark.css | 9 - .../renderer/devtools/front_end/ui/reportView.css | 4 + .../renderer/devtools/front_end/ui/splitWidget.css | 4 - .../renderer/devtools/front_end/ui/treeoutline.css | 4 - .../renderer/devtools/front_end/ui/ui_strings.grdp | 291 ++ .../devtools/front_end/ui/viewContainers.css | 11 - .../web_audio/AudioContextContentBuilder.js | 89 + .../front_end/web_audio/AudioContextSelector.js | 157 + .../devtools/front_end/web_audio/WebAudioModel.js | 115 + .../devtools/front_end/web_audio/WebAudioView.js | 185 + .../front_end/web_audio/audioContextSelector.css | 20 + .../devtools/front_end/web_audio/module.json | 29 + .../devtools/front_end/web_audio/webAudio.css | 97 + .../front_end/web_audio/web_audio_strings.grdp | 30 + .../front_end/workspace/workspace_strings.grdp | 6 + .../blink/renderer/devtools/package.json | 1 + .../scripts/build/build_release_applications.py | 3 +- .../blink/renderer/devtools/scripts/check_gn.js | 4 +- .../devtools/scripts/check_localizability.js | 174 +- .../scripts/check_localizable_resources.js | 240 + .../localization_utils/check_localized_strings.js | 384 ++ .../localization_utils/localization_utils.js | 269 ++ .../devtools/scripts/localization_utils/md5.js | 157 + .../devtools/scripts/run_old_devtools/index.js | 5 +- .../renderer/devtools/scripts/unused_css/index.js | 149 + .../devtools/scripts/unused_css/package.json | 11 + 220 files changed, 15582 insertions(+), 4076 deletions(-) create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/console_counters/console_counters_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/inline_editor/inline_editor_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/node_debugger/node_debugger_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/product_registry/product_registry_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/screencast/screencast_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp delete mode 100644 chromium/third_party/blink/renderer/devtools/front_end/sources/revisionHistory.css create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/text_editor/text_editor_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/timeline_model/timeline_model_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextContentBuilder.js create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioModel.js create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioView.js create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/audioContextSelector.css create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/module.json create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/webAudio.css create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/front_end/workspace/workspace_strings.grdp create mode 100644 chromium/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js create mode 100644 chromium/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js create mode 100644 chromium/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js create mode 100644 chromium/third_party/blink/renderer/devtools/scripts/localization_utils/md5.js create mode 100644 chromium/third_party/blink/renderer/devtools/scripts/unused_css/index.js create mode 100644 chromium/third_party/blink/renderer/devtools/scripts/unused_css/package.json (limited to 'chromium/third_party/blink/renderer/devtools') diff --git a/chromium/third_party/blink/renderer/devtools/BUILD.gn b/chromium/third_party/blink/renderer/devtools/BUILD.gn index 2db8281b9ab..a4c42c09620 100644 --- a/chromium/third_party/blink/renderer/devtools/BUILD.gn +++ b/chromium/third_party/blink/renderer/devtools/BUILD.gn @@ -255,6 +255,7 @@ all_devtools_files = [ "front_end/elements_test_runner/EditDOMTestRunner.js", "front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js", "front_end/elements_test_runner/ElementsTestRunner.js", + "front_end/elements_test_runner/module.json", "front_end/elements_test_runner/SetOuterHTMLTestRunner.js", "front_end/elements_test_runner/StylesUpdateLinksTestRunner.js", "front_end/emulated_devices/module.json", @@ -487,6 +488,7 @@ all_devtools_files = [ "front_end/persistence/FileSystemWorkspaceBinding.js", "front_end/persistence/IsolatedFileSystem.js", "front_end/persistence/IsolatedFileSystemManager.js", + "front_end/persistence/module.json", "front_end/persistence/NetworkPersistenceManager.js", "front_end/persistence/Persistence.js", "front_end/persistence/PersistenceActions.js", @@ -628,6 +630,7 @@ all_devtools_files = [ "front_end/sdk/TracingModel.js", "front_end/sdk_test_runner/module.json", "front_end/sdk_test_runner/PageMockTestRunner.js", + "front_end/search/module.json", "front_end/search/SearchConfig.js", "front_end/search/searchResultsPane.css", "front_end/search/SearchResultsPane.js", @@ -642,6 +645,7 @@ all_devtools_files = [ "front_end/security/sidebar.css", "front_end/security_test_runner/module.json", "front_end/security_test_runner/SecurityTestRunner.js", + "front_end/services/module.json", "front_end/services/ServiceManager.js", "front_end/settings/frameworkBlackboxSettingsTab.css", "front_end/settings/FrameworkBlackboxSettingsTab.js", @@ -694,13 +698,11 @@ all_devtools_files = [ "front_end/sources/NavigatorView.js", "front_end/sources/OpenFileQuickOpen.js", "front_end/sources/OutlineQuickOpen.js", - "front_end/sources/revisionHistory.css", "front_end/sources/scopeChainSidebarPane.css", "front_end/sources/ScopeChainSidebarPane.js", "front_end/sources/ScriptFormatterEditorAction.js", "front_end/sources/ScriptOriginPlugin.js", "front_end/sources/SearchSourcesView.js", - "front_end/sources/serviceWorkersSidebar.css", "front_end/sources/SimpleHistoryManager.js", "front_end/sources/SnippetsPlugin.js", "front_end/sources/SourceFormatter.js", @@ -724,6 +726,7 @@ all_devtools_files = [ "front_end/sources_test_runner/SearchTestRunner.js", "front_end/sources_test_runner/SourcesTestRunner.js", "front_end/sources_test_runner/module.json", + "front_end/terminal/module.json", "front_end/terminal/terminal.css", "front_end/terminal/TerminalWidget.js", "front_end/terminal/xterm.js/addons/fit/fit.js", @@ -873,8 +876,16 @@ all_devtools_files = [ "front_end/ui/XLink.js", "front_end/ui/XWidget.js", "front_end/ui/ZoomManager.js", + "front_end/web_audio/AudioContextContentBuilder.js", + "front_end/web_audio/audioContextSelector.css", + "front_end/web_audio/AudioContextSelector.js", + "front_end/web_audio/module.json", + "front_end/web_audio/webAudio.css", + "front_end/web_audio/WebAudioModel.js", + "front_end/web_audio/WebAudioView.js", "front_end/worker_main/WorkerMain.js", "front_end/worker_main/module.json", + "front_end/worker_service/module.json", "front_end/worker_service/ServiceDispatcher.js", "front_end/workspace/FileManager.js", "front_end/workspace/module.json", @@ -1141,6 +1152,7 @@ generated_non_autostart_non_remote_modules = [ "$resources_out_dir/text_editor/text_editor_module.js", "$resources_out_dir/timeline_model/timeline_model_module.js", "$resources_out_dir/timeline/timeline_module.js", + "$resources_out_dir/web_audio/web_audio_module.js", "$resources_out_dir/workspace_diff/workspace_diff_module.js", ] diff --git a/chromium/third_party/blink/renderer/devtools/OWNERS b/chromium/third_party/blink/renderer/devtools/OWNERS index f1601f59071..40f586c609e 100644 --- a/chromium/third_party/blink/renderer/devtools/OWNERS +++ b/chromium/third_party/blink/renderer/devtools/OWNERS @@ -1,4 +1,5 @@ dgozman@chromium.org pfeldman@chromium.org lushnikov@chromium.org +einbinder@chromium.org per-file BUILD.gn=* diff --git a/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py b/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py index 68de82a5442..f19b26668b1 100644 --- a/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py +++ b/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py @@ -94,16 +94,33 @@ def _CheckFormat(input_api, output_api): ] -def _CheckDevtoolsLocalization(input_api, output_api): # pylint: disable=invalid-name +def _CheckDevtoolsWithNodeScript(input_api, output_api, script_path, script_arguments=None): # pylint: disable=invalid-name affected_front_end_files = _getAffectedFrontEndFiles(input_api) if len(affected_front_end_files) == 0: return [] else: - affected_front_end_files = [ - input_api.os_path.join(input_api.PresubmitLocalPath(), file_path) for file_path in affected_front_end_files - ] - script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_localizability.js") - return _checkWithNodeScript(input_api, output_api, script_path, affected_front_end_files) + if script_arguments is None: + script_arguments = [] + return _checkWithNodeScript(input_api, output_api, script_path, script_arguments) + + +def _CheckDevtoolsLocalizableResources(input_api, output_api): # pylint: disable=invalid-name + affected_front_end_files = _getAffectedFrontEndFiles(input_api) + if len(affected_front_end_files) == 0: + return [] + script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_localizable_resources.js") + args = ['--autofix'] + return _CheckDevtoolsWithNodeScript(input_api, output_api, script_path, args) + + +def _CheckDevtoolsLocalization(input_api, output_api): # pylint: disable=invalid-name + affected_front_end_files = [ + input_api.os_path.join(input_api.PresubmitLocalPath(), file_path) for file_path in _getAffectedFrontEndFiles(input_api) + ] + if len(affected_front_end_files) == 0: + return [] + script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_localizability.js") + return _checkWithNodeScript(input_api, output_api, script_path, affected_front_end_files) def _CheckDevtoolsStyle(input_api, output_api): @@ -123,9 +140,9 @@ def _CheckDevtoolsStyle(input_api, output_api): def _CompileDevtoolsFrontend(input_api, output_api): compile_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "compile_frontend.py") - out, _ = input_api.subprocess.Popen( - [input_api.python_executable, compile_path], stdout=input_api.subprocess.PIPE, - stderr=input_api.subprocess.STDOUT).communicate() + out, _ = input_api.subprocess.Popen([input_api.python_executable, compile_path], + stdout=input_api.subprocess.PIPE, + stderr=input_api.subprocess.STDOUT).communicate() if "ERROR" in out or "WARNING" in out: return [output_api.PresubmitError(out)] if "NOTE" in out: @@ -202,6 +219,7 @@ def CheckChangeOnUpload(input_api, output_api): results = [] results.extend(_CheckBuildGN(input_api, output_api)) results.extend(_CheckFormat(input_api, output_api)) + results.extend(_CheckDevtoolsLocalizableResources(input_api, output_api)) results.extend(_CheckDevtoolsLocalization(input_api, output_api)) results.extend(_CheckDevtoolsStyle(input_api, output_api)) results.extend(_CompileDevtoolsFrontend(input_api, output_api)) @@ -237,7 +255,7 @@ def _getAffectedJSFiles(input_api): return [input_api.os_path.relpath(file_name, devtools_root) for file_name in affected_js_files] -def _checkWithNodeScript(input_api, output_api, script_path, files=None): # pylint: disable=invalid-name +def _checkWithNodeScript(input_api, output_api, script_path, script_arguments=None): # pylint: disable=invalid-name original_sys_path = sys.path try: sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts")] @@ -247,11 +265,11 @@ def _checkWithNodeScript(input_api, output_api, script_path, files=None): # pyl node_path = local_node.node_path() - if files is None: - files = [] + if script_arguments is None: + script_arguments = [] process = input_api.subprocess.Popen( - [node_path, script_path] + files, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT) + [node_path, script_path] + script_arguments, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT) out, _ = process.communicate() if process.returncode != 0: diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.png b/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.png index 187f2c37ffc..23523490a73 100644 Binary files a/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.png and b/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.png differ diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons_2x.png b/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons_2x.png index 310edf2b617..866dd0b1fc8 100644 Binary files a/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons_2x.png and b/chromium/third_party/blink/renderer/devtools/front_end/Images/mediumIcons_2x.png differ diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg index 3e21a093977..02c73565c65 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg +++ b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg @@ -8,11 +8,11 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="80" - height="80" + width="96" + height="96" id="svg4775" version="1.1" - inkscape:version="0.92.2pre0 (973e216, 2017-07-25)" + inkscape:version="0.92.3 (2405546, 2018-03-11)" sodipodi:docname="mediumIcons.svg" inkscape:export-filename="/Users/pfeldman/code/chromium/src/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons.png" inkscape:export-xdpi="90" @@ -95,13 +95,13 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="2714" - inkscape:window-height="1732" + inkscape:window-width="2558" + inkscape:window-height="1378" id="namedview4913" showgrid="true" inkscape:zoom="5.2149126" - inkscape:cx="-45.52086" - inkscape:cy="72.509528" + inkscape:cx="-63.677407" + inkscape:cy="76.536441" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="0" @@ -120,32 +120,32 @@ + transform="translate(0,32)"> @@ -153,12 +153,12 @@ id="g4801" style="fill:none"> @@ -166,34 +166,34 @@ @@ -317,7 +313,7 @@ @@ -351,7 +347,7 @@ x2="109.5" y1="103" y2="103" - gradientTransform="matrix(0,1,-1,0,206,0)" + gradientTransform="rotate(90,103,103)" gradientUnits="userSpaceOnUse" xlink:href="#sprite13_q" /> 1 2 3 4 a b c d + transform="translate(32,80)"> + d="M 8,1 C 4.136,1 1,4.136 1,8 c 0,3.864 3.136,7 7,7 3.864,0 7,-3.136 7,-7 C 15,4.136 11.864,1 8,1 Z M 2.5,8 C 2.5,4.968125 4.968125,2.5 8,2.5 c 3.031875,0 5.5,2.468125 5.5,5.5 0,3.031875 -2.468125,5.5 -5.5,5.5 C 4.968125,13.5 2.5,11.031875 2.5,8 Z M 9,12 V 7 H 7 v 5 z M 7,6 H 9 V 4 H 7 Z" /> @@ -595,16 +591,16 @@ + transform="matrix(0.66666667,0,0,0.66666667,64,32)"> @@ -670,56 +666,56 @@ xml:space="preserve" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:sans-serif;-inkscape-font-specification:Sans;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:0.37333332;stroke:none" x="-10.738436" - y="12.11775" + y="28.11775" id="text5090">5 e + transform="matrix(0.75,0,0,0.75,63,15)"> + transform="matrix(0.75,0,0,0.75,47,79)"> + transform="translate(48,16)"> + d="m 0.5,14 h 15 L 8,1 Z M 9,12 H 7 V 10 H 9 Z M 9,9 H 7 V 6 h 2 z" /> A B + + + + + + + + + + + + + + + + + + + + + + 6 + f + + + + + + + diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_png.hashes b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_png.hashes index 86d2d9e6cd5..83ab14975c0 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_png.hashes +++ b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_png.hashes @@ -5,7 +5,7 @@ "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a", "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45", "smallIcons.svg": "40aefe4606ebba939725954ff9f908ef", - "mediumIcons.svg": "115d211e8c00873698de4c861d7f3e44", + "mediumIcons.svg": "e2878b1c2a8e27c52d146c8942a153cb", "breakpoint.svg": "69cd92d807259c022791112809b97799", "treeoutlineTriangles.svg": "2d26ab85d919f83d5021f2f385dffd0b", "chevrons.svg": "79b4b527771e30b6388ce664077b3409" diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/svg2png.hashes b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/svg2png.hashes index 86d2d9e6cd5..83ab14975c0 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/svg2png.hashes +++ b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/svg2png.hashes @@ -5,7 +5,7 @@ "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a", "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45", "smallIcons.svg": "40aefe4606ebba939725954ff9f908ef", - "mediumIcons.svg": "115d211e8c00873698de4c861d7f3e44", + "mediumIcons.svg": "e2878b1c2a8e27c52d146c8942a153cb", "breakpoint.svg": "69cd92d807259c022791112809b97799", "treeoutlineTriangles.svg": "2d26ab85d919f83d5021f2f385dffd0b", "chevrons.svg": "79b4b527771e30b6388ce664077b3409" diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png b/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png index 24178c59789..1ecc4371744 100644 Binary files a/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png and b/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png differ diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js b/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js index 28cb0dcc11b..af2dd89a853 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js @@ -378,6 +378,13 @@ var Runtime = class { // eslint-disable-line return '\n/*# sourceURL=' + sourceURL + ' */'; } + /** + * @param {function(string):string} localizationFunction + */ + static setL10nCallback(localizationFunction) { + Runtime._l10nCallback = localizationFunction; + } + useTestBase() { Runtime._remoteBase = 'http://localhost:8000/inspector-sources/'; if (Runtime.queryParam('debugFrontend')) @@ -890,8 +897,10 @@ Runtime.Extension = class { * @return {string} */ title() { - // FIXME: should be Common.UIString() but runtime is not l10n aware yet. - return this._descriptor['title-' + Runtime._platform] || this._descriptor['title']; + const title = this._descriptor['title-' + Runtime._platform] || this._descriptor['title']; + if (title && Runtime._l10nCallback) + return Runtime._l10nCallback(title); + return title; } /** @@ -1071,12 +1080,16 @@ Runtime.experiments = new Runtime.ExperimentsSupport(); /** @type {Function} */ Runtime._appStartedPromiseCallback; Runtime._appStartedPromise = new Promise(fulfil => Runtime._appStartedPromiseCallback = fulfil); + +/** @type {function(string):string} */ +Runtime._l10nCallback; + /** * @type {?string} */ Runtime._remoteBase; (function validateRemoteBase() { - if (location.href.startsWith('chrome-devtools://devtools/bundled/') && Runtime.queryParam('remoteBase')) { + if (location.href.startsWith('devtools://devtools/bundled/') && Runtime.queryParam('remoteBase')) { const versionMatch = /\/serve_file\/(@[0-9a-zA-Z]+)\/?$/.exec(Runtime.queryParam('remoteBase')); if (versionMatch) Runtime._remoteBase = `${location.origin}/remote/serve_file/${versionMatch[1]}/`; diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Tests.js b/chromium/third_party/blink/renderer/devtools/front_end/Tests.js index 9ffe80ab401..255e7de1b65 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/Tests.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/Tests.js @@ -763,6 +763,89 @@ {type: 'keyUp', windowsVirtualKeyCode: 0x23, key: 'End'}); }; + // Check that showing the certificate viewer does not crash, crbug.com/954874 + TestSuite.prototype.testShowCertificate = function() { + InspectorFrontendHost.showCertificateViewer([ + 'MIIFIDCCBAigAwIBAgIQE0TsEu6R8FUHQv+9fE7j8TANBgkqhkiG9w0BAQsF' + + 'ADBUMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp' + + 'Y2VzMSUwIwYDVQQDExxHb29nbGUgSW50ZXJuZXQgQXV0aG9yaXR5IEczMB4X' + + 'DTE5MDMyNjEzNDEwMVoXDTE5MDYxODEzMjQwMFowZzELMAkGA1UEBhMCVVMx' + + 'EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcx' + + 'EzARBgNVBAoMCkdvb2dsZSBMTEMxFjAUBgNVBAMMDSouYXBwc3BvdC5jb20w' + + 'ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwca7hj0kyoJVxcvyA' + + 'a8zNKMIXcoPM3aU1KVe7mxZITtwC6/D/D/q4Oe8fBQLeZ3c6qR5Sr3M+611k' + + 'Ab15AcGUgh1Xi0jZqERvd/5+P0aVCFJYeoLrPBzwSMZBStkoiO2CwtV8x06e' + + 'X7qUz7Hvr3oeG+Ma9OUMmIebl//zHtC82mE0mCRBQAW0MWEgT5nOWey74tJR' + + 'GRqUEI8ftV9grAshD5gY8kxxUoMfqrreaXVqcRF58ZPiwUJ0+SbtC5q9cJ+K' + + 'MuYM4TCetEuk/WQsa+1EnSa40dhGRtZjxbwEwQAJ1vLOcIA7AVR/Ck22Uj8X' + + 'UOECercjUrKdDyaAPcLp2TThAgMBAAGjggHZMIIB1TATBgNVHSUEDDAKBggr' + + 'BgEFBQcDATCBrwYDVR0RBIGnMIGkgg0qLmFwcHNwb3QuY29tggsqLmEucnVu' + + 'LmFwcIIVKi50aGlua3dpdGhnb29nbGUuY29tghAqLndpdGhnb29nbGUuY29t' + + 'ghEqLndpdGh5b3V0dWJlLmNvbYILYXBwc3BvdC5jb22CB3J1bi5hcHCCE3Ro' + + 'aW5rd2l0aGdvb2dsZS5jb22CDndpdGhnb29nbGUuY29tgg93aXRoeW91dHVi' + + 'ZS5jb20waAYIKwYBBQUHAQEEXDBaMC0GCCsGAQUFBzAChiFodHRwOi8vcGtp' + + 'Lmdvb2cvZ3NyMi9HVFNHSUFHMy5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6Ly9v' + + 'Y3NwLnBraS5nb29nL0dUU0dJQUczMB0GA1UdDgQWBBTGkpE5o0H9+Wjc05rF' + + 'hNQiYDjBFjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFHfCuFCaZ3Z2sS3C' + + 'htCDoH6mfrpLMCEGA1UdIAQaMBgwDAYKKwYBBAHWeQIFAzAIBgZngQwBAgIw' + + 'MQYDVR0fBCowKDAmoCSgIoYgaHR0cDovL2NybC5wa2kuZ29vZy9HVFNHSUFH' + + 'My5jcmwwDQYJKoZIhvcNAQELBQADggEBALqoYGqWtJW/6obEzY+ehsgfyXb+' + + 'qNIuV09wt95cRF93HlLbBlSZ/Iz8HXX44ZT1/tGAkwKnW0gDKSSab3I8U+e9' + + 'LHbC9VXrgAFENzu89MNKNmK5prwv+MPA2HUQPu4Pad3qXmd4+nKc/EUjtg1d' + + '/xKGK1Vn6JX3i5ly/rduowez3LxpSAJuIwseum331aQaKC2z2ri++96B8MPU' + + 'KFXzvV2gVGOe3ZYqmwPaG8y38Tba+OzEh59ygl8ydJJhoI6+R3itPSy0aXUU' + + 'lMvvAbfCobXD5kBRQ28ysgbDSDOPs3fraXpAKL92QUjsABs58XBz5vka4swu' + + 'gg/u+ZxaKOqfIm8=', + 'MIIEXDCCA0SgAwIBAgINAeOpMBz8cgY4P5pTHTANBgkqhkiG9w0BAQsFADBM' + + 'MSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMK' + + 'R2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAw' + + 'NDJaFw0yMTEyMTUwMDAwNDJaMFQxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVH' + + 'b29nbGUgVHJ1c3QgU2VydmljZXMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5l' + + 'dCBBdXRob3JpdHkgRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB' + + 'AQDKUkvqHv/OJGuo2nIYaNVWXQ5IWi01CXZaz6TIHLGp/lOJ+600/4hbn7vn' + + '6AAB3DVzdQOts7G5pH0rJnnOFUAK71G4nzKMfHCGUksW/mona+Y2emJQ2N+a' + + 'icwJKetPKRSIgAuPOB6Aahh8Hb2XO3h9RUk2T0HNouB2VzxoMXlkyW7XUR5m' + + 'w6JkLHnA52XDVoRTWkNty5oCINLvGmnRsJ1zouAqYGVQMc/7sy+/EYhALrVJ' + + 'EA8KbtyX+r8snwU5C1hUrwaW6MWOARa8qBpNQcWTkaIeoYvy/sGIJEmjR0vF' + + 'EwHdp1cSaWIr6/4g72n7OqXwfinu7ZYW97EfoOSQJeAzAgMBAAGjggEzMIIB' + + 'LzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF' + + 'BwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHfCuFCaZ3Z2sS3C' + + 'htCDoH6mfrpLMB8GA1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd/cGYYuMDUG' + + 'CCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdv' + + 'b2cvZ3NyMjAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29n' + + 'L2dzcjIvZ3NyMi5jcmwwPwYDVR0gBDgwNjA0BgZngQwBAgIwKjAoBggrBgEF' + + 'BQcCARYcaHR0cHM6Ly9wa2kuZ29vZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0B' + + 'AQsFAAOCAQEAHLeJluRT7bvs26gyAZ8so81trUISd7O45skDUmAge1cnxhG1' + + 'P2cNmSxbWsoiCt2eux9LSD+PAj2LIYRFHW31/6xoic1k4tbWXkDCjir37xTT' + + 'NqRAMPUyFRWSdvt+nlPqwnb8Oa2I/maSJukcxDjNSfpDh/Bd1lZNgdd/8cLd' + + 'sE3+wypufJ9uXO1iQpnh9zbuFIwsIONGl1p3A8CgxkqI/UAih3JaGOqcpcda' + + 'CIzkBaR9uYQ1X4k2Vg5APRLouzVy7a8IVk6wuy6pm+T7HT4LY8ibS5FEZlfA' + + 'FLSW8NwsVz9SBK2Vqn1N0PIMn5xA6NZVc7o835DLAFshEWfC7TIe3g==', + 'MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEg' + + 'MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkds' + + 'b2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAw' + + 'WhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3Qg' + + 'Q0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs' + + 'U2lnbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8o' + + 'mUVCxKs+IVSbC9N/hHD6ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe' + + '+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1' + + 'AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjNS7SgfQx5' + + 'TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo' + + '4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99y' + + 'qWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8E' + + 'BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IHV2ccHsBqBt5Z' + + 'tJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9iYWxz' + + 'aWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0' + + 'mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs' + + 'J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4' + + 'h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRD' + + 'LenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7' + + '9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmg' + + 'QWpzU/qlULRuJQ/7TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq' + + '/H5COEBkEveegeGTLg==' + ]); + }; + // Simple sanity check to make sure network throttling is wired up // See crbug.com/747724 TestSuite.prototype.testOfflineNetworkConditions = async function() { @@ -1329,6 +1412,33 @@ this.releaseControl(); }; + TestSuite.prototype.testExtensionWebSocketUserAgentOverride = async function(websocketPort) { + this.takeControl(); + + const testUserAgent = 'test user agent'; + SDK.multitargetNetworkManager.setUserAgentOverride(testUserAgent); + + function onRequestUpdated(event) { + const request = event.data; + if (request.resourceType() !== Common.resourceTypes.WebSocket) + return; + if (!request.requestHeadersText()) + return; + + let actualUserAgent = 'no user-agent header'; + for (const {name, value} of request.requestHeaders()) { + if (name.toLowerCase() === 'user-agent') + actualUserAgent = value; + } + this.assertEquals(testUserAgent, actualUserAgent); + this.releaseControl(); + } + SDK.targetManager.addModelListener( + SDK.NetworkManager, SDK.NetworkManager.Events.RequestUpdated, onRequestUpdated.bind(this)); + + this.evaluateInConsole_(`new WebSocket('ws://127.0.0.1:${websocketPort}')`, () => {}); + }; + /** * Serializes array of uiSourceCodes to string. * @param {!Array.} uiSourceCodes diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibilityNode.css b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibilityNode.css index 7b624a9e021..bcb8f758112 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibilityNode.css +++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibilityNode.css @@ -4,20 +4,11 @@ * found in the LICENSE file. */ -.sidebar-pane.accessibility-computed { - background-color: rgba(0, 0, 0, 0.03); -} - .widget.ax-subpane { overflow-x: hidden; -webkit-user-select: text; } -div.ax-text-alternatives { - margin-bottom: 3px; - border-bottom: 1px solid #BFBFBF; -} - .ax-ignored-info { padding: 6px; } @@ -43,10 +34,6 @@ span.ax-value-undefined { text-decoration: line-through; } -.sidebar-pane-stack .sidebar-pane { - padding-left: 4px; -} - .tree-outline span[is=dt-icon-label] { position: relative; left: -11px; diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp new file mode 100644 index 00000000000..4023c8cb4ff --- /dev/null +++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp @@ -0,0 +1,90 @@ + + + + Computed Properties + + + Element not interesting for accessibility. + + + Element has empty alt text. + + + Element inherits presentational role from  + + + Element is inert. + + + Ancestor's children are all presentational:  + + + Element is $1s. + + + No ARIA attributes + + + Static text node is used as name for  + + + No node with this ID. + + + Element is presentational. + + + ARIA Attributes + + + Scroll into view + + + Accessibility node not exposed + + + Element is not visible. + + + Accessibility Tree + + + No accessibility node + + + Part of label element:  + + + Element is not rendered. + + + Element is hidden by active modal dialog:  + + + $1s is $2s on ancestor:  + + + Element has $1s. + + + Ignored + + + Not specified + + + Invalid source. + + + Accessibility + + + Label for  + + + Element is in an inert subtree from  + + + No text content. + + \ No newline at end of file diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/animationTimeline.css b/chromium/third_party/blink/renderer/devtools/front_end/animation/animationTimeline.css index 37f109c646e..8155fb49917 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/animation/animationTimeline.css +++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/animationTimeline.css @@ -289,19 +289,6 @@ text.animation-timeline-grid-label { background-color: #EFF4FD; } -.animation-timeline-empty-message { - padding-left: 230px; - padding-right: 30px; - text-align: center; - position: absolute; - font-size: 20px; - line-height: 32px; - align-items: center; justify-content: center; - width: 100%; - height: calc(100% - 44px); - display: flex; -} - .animation-buffer-preview { height: 40px; margin: 4px 2px; diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp new file mode 100644 index 00000000000..656e1fb140b --- /dev/null +++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp @@ -0,0 +1,39 @@ + + + + Animations + + + Pause + + + Set speed to $1s + + + Pause timeline + + + $1s% + + + Clear all + + + Pause all + + + Play timeline + + + Select an effect above to inspect and modify. + + + Listening for animations... + + + Replay timeline + + + Resume all + + \ No newline at end of file diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js index 6869d7c22f0..6b5b9e4eb46 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js @@ -199,32 +199,32 @@ Audits2.Presets = [ { setting: Common.settings.createSetting('audits2.cat_perf', true), configID: 'performance', - title: 'Performance', - description: 'How long does this app take to show content and become usable' + title: ls`Performance`, + description: ls`How long does this app take to show content and become usable` }, { setting: Common.settings.createSetting('audits2.cat_pwa', true), configID: 'pwa', - title: 'Progressive Web App', - description: 'Does this page meet the standard of a Progressive Web App' + title: ls`Progressive Web App`, + description: ls`Does this page meet the standard of a Progressive Web App` }, { setting: Common.settings.createSetting('audits2.cat_best_practices', true), configID: 'best-practices', - title: 'Best practices', - description: 'Does this page follow best practices for modern web development' + title: ls`Best practices`, + description: ls`Does this page follow best practices for modern web development` }, { setting: Common.settings.createSetting('audits2.cat_a11y', true), configID: 'accessibility', - title: 'Accessibility', - description: 'Is this page usable by people with disabilities or impairments' + title: ls`Accessibility`, + description: ls`Is this page usable by people with disabilities or impairments` }, { setting: Common.settings.createSetting('audits2.cat_seo', true), configID: 'seo', - title: 'SEO', - description: 'Is this page optimized for search engine results ranking' + title: ls`SEO`, + description: ls`Is this page optimized for search engine results ranking` }, ]; @@ -237,7 +237,9 @@ Audits2.RuntimeSettings = [ setting: Common.settings.createSetting('audits2.device_type', 'mobile'), description: ls`Apply mobile emulation during auditing`, setFlags: (flags, value) => { - flags.disableDeviceEmulation = value === 'desktop'; + flags._devtoolsEmulationType = value; + // See Audits.AuditsPanel._setupEmulationAndProtocolConnection() + flags.emulatedFormFactor = 'none'; }, options: [ {label: ls`Mobile`, value: 'mobile'}, @@ -260,19 +262,19 @@ Audits2.RuntimeSettings = [ }, options: [ { - label: ls`Simulated Fast 3G, 4x CPU Slowdown`, + label: ls`Simulated Slow 4G, 4x CPU Slowdown`, value: 'default', - title: 'Throttling is simulated, resulting in faster audit runs with similar measurement accuracy' + title: ls`Throttling is simulated, resulting in faster audit runs with similar measurement accuracy` }, { - label: ls`Applied Fast 3G, 4x CPU Slowdown`, + label: ls`Applied Slow 4G, 4x CPU Slowdown`, value: 'devtools', - title: 'Typical DevTools throttling, with actual traffic shaping and CPU slowdown applied' + title: ls`Typical DevTools throttling, with actual traffic shaping and CPU slowdown applied` }, { label: ls`No throttling`, value: 'off', - title: 'No network or CPU throttling used. (Useful when not evaluating performance)' + title: ls`No network or CPU throttling used. (Useful when not evaluating performance)` }, ], }, diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Panel.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Panel.js index 8d2053410da..3a0d2cc1baf 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Panel.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Panel.js @@ -148,6 +148,11 @@ Audits2.Audits2Panel = class extends UI.Panel { const el = renderer.renderReport(lighthouseResult, reportContainer); Audits2.ReportRenderer.addViewTraceButton(el, artifacts); Audits2.ReportRenderer.linkifyNodeDetails(el); + Audits2.ReportRenderer.handleDarkMode(el); + + const features = new ReportUIFeatures(dom); + features.setTemplateContext(templatesDOM); + features.initFeatures(lighthouseResult); this._cachedRenderedReports.set(lighthouseResult, reportContainer); } @@ -237,6 +242,12 @@ Audits2.Audits2Panel = class extends UI.Panel { this._renderStartView(); } + /** + * We set the device emulation on the DevTools-side for two reasons: + * 1. To workaround some odd device metrics emulation bugs like occuluding viewports + * 2. To get the attractive device outline + * flags.emulatedFormFactor is always set to none, so Lighthouse doesn't apply its own emulation. + */ async _setupEmulationAndProtocolConnection() { const flags = this._controller.getFlags(); @@ -245,11 +256,10 @@ Audits2.Audits2Panel = class extends UI.Panel { this._emulationOutlineEnabledBefore = emulationModel.deviceOutlineSetting().get(); emulationModel.toolbarControlsEnabledSetting().set(false); - if (flags.disableDeviceEmulation) { + if (flags._devtoolsEmulationType === 'desktop') { emulationModel.enabledSetting().set(false); - emulationModel.deviceOutlineSetting().set(false); emulationModel.emulate(Emulation.DeviceModeModel.Type.None, null, null); - } else { + } else if (flags._devtoolsEmulationType === 'mobile') { emulationModel.enabledSetting().set(true); emulationModel.deviceOutlineSetting().set(true); diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportRenderer.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportRenderer.js index 62487a82756..e004e7f55cf 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportRenderer.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportRenderer.js @@ -57,4 +57,12 @@ Audits2.ReportRenderer = class extends ReportRenderer { origElement.appendChild(element); } } + + /** + * @param {!Element} el + */ + static handleDarkMode(el) { + if (UI.themeSupport.themeName() === 'dark') + el.classList.add('dark'); + } }; diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StartView.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StartView.js index cd3eae4a09b..c7eb7ccc99b 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StartView.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StartView.js @@ -87,10 +87,11 @@ Audits2.StartView = class extends UI.Widget {
-

Audits

+

${ls`Audits`}

- Identify and fix common problems that affect your site's performance, accessibility, and user experience. - Learn more + ${ls`Identify and fix common problems that affect your site's performance, + accessibility, and user experience.`} + ${ls`Learn more`}

@@ -98,21 +99,21 @@ Audits2.StartView = class extends UI.Widget {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StatusView.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StatusView.js index 149eb45e8ac..01335774ead 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StatusView.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2StatusView.js @@ -273,14 +273,14 @@ Audits2.StatusView.StatusPhases = [ id: 'gathering', progressBarClass: 'gathering', message: 'Lighthouse is gathering information about the page to compute your score.', - statusMessagePrefix: 'Retrieving', + statusMessagePrefix: 'Gathering', order: 20, }, { id: 'auditing', progressBarClass: 'auditing', message: 'Almost there! Lighthouse is now generating your report.', - statusMessagePrefix: 'Evaluating', + statusMessagePrefix: 'Auditing', order: 30, } ]; diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Dialog.css b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Dialog.css index 60a4b747a78..0ab61279296 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Dialog.css +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Dialog.css @@ -108,8 +108,3 @@ 0% { width: var(--progress-bar-auditing-percent); } 100% { width: 99%; } } - -.audits2-report-error { - display: block; - margin-top: 5px; -} diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css index 92ee823f463..5db7549a03e 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css @@ -12,33 +12,6 @@ .lh-root { --report-menu-width: 0; user-select: text; - --lh-bg-color: #fff; - background-color: var(--lh-bg-color); -} - -.-theme-with-dark-background .lh-root { - --header-bg-color: hsl(0, 0%, 20%); - --lh-table-header-bg: hsl(0, 0%, 20%); - --display-value-gray: hsl(0, 0%, 66%); - --medium-75-gray: hsl(0, 0%, 66%); - - --subheader-color: hsl(210, 15%, 80%); - --lh-bg-color: hsl(0, 0%, 14%); - --secondary-text-color: hsl(0, 0%, 66%); - --report-secondary-border-color: hsl(0, 0%, 8%); -} - -.-theme-with-dark-background .lh-root .lh-gauge { - --circle-background: hsl(0, 0%, 27%); - --inset-color: var(--lh-bg-color); -} - -.lh-root .lh-container { - word-wrap: normal; -} - -.lh-root pre { - word-wrap: break-word; } /* for View Trace button */ @@ -50,33 +23,5 @@ button.view-trace { } .audits2-results-container { - overflow-y: scroll; position: relative; } - -/* TODO(phulce): remove the below on next LH roll */ - -.-theme-with-dark-background .lh-scores-wrapper__background, .-theme-with-dark-background .lh-scores-wrapper__shadow { - background: var(--lh-bg-color) !important; -} - -.-theme-with-dark-background .lh-gauge__label { - color: hsl(210, 15%, 80%); -} - -.-theme-with-dark-background .lh-root .lh-audit a, .-theme-with-dark-background .lh-footer a { - color: hsl(210, 90%, 60%); -} - -.-theme-with-dark-background .lh-load-opportunity__header .lh-load-opportunity__col { - background: hsl(0, 0%, 20%); -} - -.-theme-with-dark-background .lh-crc .crc-node__tree-hostname { - color: hsl(0, 0%, 66%); -} - -.-theme-with-dark-background .lh-audit-group__header::before { - background-color: hsl(0, 0%, 80%); - filter: invert(1); -} \ No newline at end of file diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2_strings.grdp new file mode 100644 index 00000000000..8202dda3ed0 --- /dev/null +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2_strings.grdp @@ -0,0 +1,148 @@ + + + + Auditing your web page + + + Progressive Web App + + + Simulated Slow 4G, 4x CPU Slowdown + + + 💡 $1s + + + Run audits + + + Loading… + + + No network or CPU throttling used. (Useful when not evaluating performance) + + + View Trace + + + Apply mobile emulation during auditing + + + Typical DevTools throttling, with actual traffic shaping and CPU slowdown applied + + + $1s + + + Desktop + + + Can only audit HTTP/HTTPS pages and Chrome extensions. Navigate to a different page to start an audit. + + + Lighthouse is loading your page + + + How long does this app take to show content and become usable + + + No throttling + + + Applied Slow 4G, 4x CPU Slowdown + + + Throttling + + + Throttling is simulated, resulting in faster audit runs with similar measurement accuracy + + + Try to navigate to the URL in a fresh Chrome profile without any other tabs or extensions open and try again. + + + Perform an audit… + + + Cancelling + + + Ah, sorry! We ran into an error. + + + Cancelling… + + + Is this page usable by people with disabilities or impairments + + + At least one category must be selected. + + + Download report + + + Multiple tabs are being controlled by the same service worker. Close your other tabs on the same origin to audit this page. + + + Is this page optimized for search engine results ranking + + + (new audit) + + + Mobile + + + Auditing $1s + + + Lighthouse is warming up… + + + Reset storage (localStorage, IndexedDB, etc) before auditing. (Good for performance & PWA testing) + + + Performance + + + Audits + + + Does this page meet the standard of a Progressive Web App + + + Clear storage + + + Does this page follow best practices for modern web development + + + Best practices + + + Identify and fix common problems that affect your site's performance, + accessibility, and user experience. + + + Reports + + + Learn more + + + SEO + + + Device + + + Drop audit file here + + + Cancel + + + If this issue is reproducible, please report it at the Lighthouse GitHub repo. + + \ No newline at end of file diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.css b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.css index 0c579479e69..8a0d5e4c167 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.css +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.css @@ -17,10 +17,11 @@ .lh-vars { --text-font-family: Roboto, Helvetica, Arial, sans-serif; - --monospace-font-family: 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace; + --monospace-font-family: 'Roboto Mono', 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace; --body-background-color: #fff; - --body-font-size: 14px; - --body-line-height: 18px; + --body-text-color: var(--color-black-900); + --body-font-size: 16px; + --body-line-height: 24px; --subheader-font-size: 14px; --subheader-line-height: 20px; --subheader-color: hsl(206, 6%, 25%); @@ -39,17 +40,13 @@ --audit-indent: 16px; --text-indent: 8px; --expandable-indent: 20px; - --secondary-text-color: #565656; + --secondary-text-color: var(--color-black-800); /*--accent-color: #3879d9;*/ - --fail-color: hsl(1, 73%, 45%); - --average-color: hsl(31, 100%, 45%); /* md orange 800 */ - --pass-color: hsl(139, 70%, 30%); - --informative-color: #0c50c7; + --informative-color: var(--color-blue-900); --medium-75-gray: #757575; --medium-50-gray: hsl(210, 17%, 98%); --medium-100-gray: hsl(200, 12%, 95%); --warning-color: #ffab00; /* md amber a700 */ - --report-border-color: #ccc; --report-secondary-border-color: #ebebeb; --metric-timeline-rule-color: #b3b3b3; --display-value-gray: hsl(216, 5%, 39%); @@ -66,13 +63,14 @@ --lh-score-highlight-bg: hsla(0, 0%, 90%, 0.2); --lh-score-icon-background-size: 24px; --lh-group-icon-background-size: var(--lh-score-icon-background-size); + --lh-export-icon-size: var(--lh-score-icon-background-size); + --lh-export-icon-color: var(--medium-75-gray); --lh-score-margin: 12px; --lh-table-header-bg: #f8f9fa; --lh-table-higlight-bg: hsla(0, 0%, 75%, 0.1); --lh-sparkline-height: 5px; --lh-sparkline-thin-height: 3px; --lh-filmstrip-thumbnail-width: 60px; - --lh-score-icon-width: calc(var(--body-font-size) / 14 * 16); --lh-category-score-width: calc(5 * var(--body-font-size)); --lh-audit-vpadding: 8px; --lh-audit-index-width: 18px; @@ -80,37 +78,174 @@ --lh-audit-group-vpadding: 8px; --lh-section-vpadding: 12px; --chevron-size: 12px; - --circle-size: calc(3 * var(--header-font-size)); + --inner-audit-left-padding: calc(var(--score-shape-size) + var(--score-shape-margin-left) + var(--score-shape-margin-right)); + + /* Palette using Material Design Colors + * https://www.materialui.co/colors */ + --color-black-100: #F5F5F5; + --color-black-200: #E0E0E0; + --color-black-400: #BDBDBD; + --color-black-500: #9E9E9E; + --color-black-600: #757575; + --color-black-800: #424242; + --color-black-900: #212121; + --off-black: #111111; + --color-black: #000000; + --color-blue: #2962FF; + --color-green-700: #018642; + --color-green: #0CCE6B; + --color-orange-700: #D04900; + --color-orange: #FFA400; + --color-red-700: #EB0F00; + --color-red: #FF4E42; + --color-white: #FFFFFF; + --color-blue-200: #90CAF9; + --color-blue-900: #0D47A1; + --color-cyan-500: #00BCD4; + --color-teal-600: #00897B; + + + /* TODO(cjamcl) clean up unused variables. */ + --audits-margin-bottom: 40px; + --env-item-bg: var(--color-black-100); + --env-name-min-width: 220px; + --env-tem-padding: 10px 0px; + --expandable-padding: 0 0 2px calc(var(--score-shape-margin-left) + var(--score-shape-size) + var(--score-shape-margin-right)); + --gauge-circle-size-big: 112px; + --gauge-circle-size: 80px; + --header-padding: 20px 0 20px 0; + --highlighter-bg: var(--color-black-400); + --icon-square-size: calc(var(--score-shape-size) * 0.88); + --plugin-badge-bg: var(--color-white); + --plugin-badge-size-big: calc(var(--gauge-circle-size-big) / 2.7); + --plugin-badge-size: calc(var(--gauge-circle-size) / 2.7); + --plugin-icon-size: 65%; + --pwa-icon-margin: 0 6px 0 -2px; + --pwa-icon-size: var(--topbar-icon-size); + --score-container-padding: 8px; + --score-container-width: 148px; + --score-number-font-size-big: 38px; + --score-number-font-size: 28px; + --score-shape-margin-left: 4px; + --score-shape-margin-right: 12px; + --score-shape-margin: 0 var(--score-shape-margin-right) 0 var(--score-shape-margin-left); + --score-shape-size: 12px; + --score-title-font-size-big: 28px; + --score-title-font-size: 20px; + --score-title-line-height-big: 36px; + --score-title-line-height: 26px; + --scorescale-height: 6px; + --scorescale-width: 18px; + --section-padding: 40px; + --topbar-bg: var(--color-black-100); + --topbar-height: 32px; + --topbar-icon-size: 24px; + --topbar-padding: 0 8px; + --metrics-toggle-color: var(--color-black-200); + + --color-average-secondary: var(--color-orange-700); + --color-average: var(--color-orange); + --color-fail-secondary: var(--color-red-700); + --color-fail: var(--color-red); + --color-pass-secondary: var(--color-green-700); + --color-pass: var(--color-green); + --color-sticky-header-bg: var(--body-background-color); + --color-highlighter-bg: var(--body-text-color); + + --color-hover: #FAFAFA; + --color-metric-toggle-lines: #7F7F7F; + + --plugin-icon-url: url('data:image/svg+xml;utf8,'); + --plugin-icon-url-dark: url('data:image/svg+xml;utf8,'); --pass-icon-url: url('data:image/svg+xml;utf8,check'); --average-icon-url: url('data:image/svg+xml;utf8,info'); --fail-icon-url: url('data:image/svg+xml;utf8,warn'); - --content-paste-icon-url: url('data:image/svg+xml;utf8,'); - --av-timer-icon-url: url('data:image/svg+xml;utf8,'); - --photo-filter-icon-url: url('data:image/svg+xml;utf8,'); - --visibility-icon-url: url('data:image/svg+xml;utf8,'); - --check-circle-icon-url: url('data:image/svg+xml;utf8,'); - --check-icon-url: url('data:image/svg+xml;utf8,'); - - --warning-icon-url: url('data:image/svg+xml;utf8,warn'); - --search-icon-url: url('data:image/svg+xml;utf8,'); - --remove-circle-icon-url: url('data:image/svg+xml;utf8,'); - --pwa-fast-reliable-gray-url: url('data:image/svg+xml;utf8,'); --pwa-installable-gray-url: url('data:image/svg+xml;utf8,'); --pwa-optimized-gray-url: url('data:image/svg+xml;utf8,'); - --pwa-fast-reliable-color-url: url('data:image/svg+xml;utf8,'); - --pwa-installable-color-url: url('data:image/svg+xml;utf8,'); - --pwa-optimized-color-url: url('data:image/svg+xml;utf8,'); + --pwa-fast-reliable-gray-url-dark: url('data:image/svg+xml;utf8,'); + --pwa-installable-gray-url-dark: url('data:image/svg+xml;utf8,'); + --pwa-optimized-gray-url-dark: url('data:image/svg+xml;utf8,'); + + --pwa-fast-reliable-color-url: url('data:image/svg+xml;utf8,'); + --pwa-installable-color-url: url('data:image/svg+xml;utf8,'); + --pwa-optimized-color-url: url('data:image/svg+xml;utf8,'); +} + +.lh-vars.dark { + --color-red-700: var(--color-red); + --color-green-700: var(--color-green); + --color-teal-600: var(--color-cyan-500); + --color-orange-700: var(--color-orange); + + --color-black-200: var(--color-black-800); + --color-black-400: var(--color-black-600); + --color-black-600: var(--color-black-500); + + --topbar-bg: var(--color-black); + --plugin-badge-bg: var(--color-black-800); + --header-bg-color: var(--color-black-900); + --env-item-bg: var(--color-black); + --report-secondary-border-color: var(--color-black-200); + + --body-background-color: var(--color-black-900); + --body-text-color: var(--color-black-100); + --secondary-text-color: var(--color-black-400); + + --highlighter-bg: var(--color-black-200); + --plugin-icon-url: var(--plugin-icon-url-dark); + + --informative-color: var(--color-blue-200); + + --medium-50-gray: #757575; + --medium-75-gray: var(--color-white); + + --color-hover: rgba(0, 0, 0, 0.2); + + --pwa-fast-reliable-gray-url: var(--pwa-fast-reliable-gray-url-dark); + --pwa-installable-gray-url: var(--pwa-installable-gray-url-dark); + --pwa-optimized-gray-url: var(--pwa-optimized-gray-url-dark); +} + +@media only screen and (max-width: 480px) { + .lh-vars { + --audits-margin-bottom: 20px; + --body-font-size: 14px; + --body-line-height: 20px; + --env-name-min-width: 120px; + --gauge-circle-size-big: 96px; + --gauge-circle-size: 72px; + --header-padding: 16px 0 16px 0; + --plugin-icon-size: 75%; + --pwa-icon-margin: 0 7px 0 -3px; + --score-container-width: 112px; + --score-number-font-size-big: 34px; + --score-number-font-size: 26px; + --score-shape-margin-left: 2px; + --score-shape-size: 10px; + --score-title-font-size-big: 22px; + --score-title-font-size: 14px; + --score-title-line-height-big: 26px; + --score-title-line-height: 20px; + --section-padding: 24px; + --topbar-height: 28px; + --topbar-icon-size: 20px; + } + + /* Not enough space to adequately show the relative savings bars. */ + .lh-sparkline { + display: none; + } } .lh-vars.lh-devtools { --text-font-family: '.SFNSDisplay-Regular', 'Helvetica Neue', 'Lucida Grande', sans-serif; --monospace-font-family: 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace; --body-font-size: 12px; - --body-line-height: 16px; + --body-line-height: 20px; --subheader-font-size: 14px; --subheader-line-height: 18px; --header-font-size: 16px; @@ -126,19 +261,50 @@ --audit-indent: 16px; --expandable-indent: 16px; + --gauge-circle-size-big: 72px; + --gauge-circle-size: 64px; + + --audits-margin-bottom: 20px; + --env-name-min-width: 120px; + --header-padding: 16px 0 16px 0; + --plugin-icon-size: 75%; + --pwa-icon-margin: 0 7px 0 -3px; + --score-container-width: 97px; + --score-number-font-size-big: 34px; + --score-number-font-size: 26px; + --score-shape-margin-left: 2px; + --score-shape-size: 10px; + --score-title-font-size-big: 22px; + --score-title-font-size: 14px; + --score-title-line-height-big: 26px; + --score-title-line-height: 20px; + --lh-audit-vpadding: 4px; --lh-audit-hgap: 12px; --lh-audit-group-vpadding: 12px; --lh-section-vpadding: 8px; } +.lh-devtools.lh-root { + height: 100%; +} +.lh-devtools .lh-container { + overflow-y: scroll; + height: calc(100% - var(--topbar-height)); +} +.lh-devtools .lh-sticky-header { + /* Is normally the height of the topbar. */ + top: 0; +} + @keyframes fadeIn { 0% { opacity: 0;} 100% { opacity: 0.6;} } -.lh-root * { +.lh-root *, .lh-root *::before, .lh-root *::after { box-sizing: border-box; + -webkit-font-smoothing: antialiased; } .lh-root { @@ -148,6 +314,7 @@ line-height: var(--body-line-height); background: var(--body-background-color); scroll-behavior: smooth; + color: var(--body-text-color); } .lh-root :focus { @@ -166,13 +333,35 @@ cursor: pointer; } +.lh-container { + /* + Text wrapping in the report is so much FUN! + We have a `word-break: break-word;` globally here to prevent a few common scenarios, namely + long non-breakable text (usually URLs) found in: + 1. The footer + 2. .lh-node (outerHTML) + 3. .lh-code + + With that sorted, the next challenge is appropriate column sizing and text wrapping inside our + .lh-details tables. Even more fun. + * We don't want table headers ("Potential Savings (ms)") to wrap or their column values, but + we'd be happy for the URL column to wrap if the URLs are particularly long. + * We want the narrow columns to remain narrow, providing the most column width for URL + * We don't want the table to extend past 100% width. + * Long URLs in the URL column can wrap. Util.getURLDisplayName maxes them out at 64 characters, + but they do not get any overflow:ellipsis treatment. + */ + word-break: break-word; +} + .lh-audit-group a, -.lh-category-header__description a { - color: #0c50c7; +.lh-category-header__description a, +.lh-audit__description a, +.lh-footer a { + color: var(--informative-color); } -.lh-audit__description { - --inner-audit-left-padding: calc(var(--text-indent) + var(--lh-audit-index-width) + 2 * var(--audit-item-gap)); +.lh-audit__description, .lh-audit__stackpack { --inner-audit-right-padding: calc(var(--text-indent) + 2px); padding-left: var(--inner-audit-left-padding); padding-right: var(--inner-audit-right-padding); @@ -184,6 +373,7 @@ font-size: var(--body-font-size); margin-top: var(--default-padding); margin-bottom: var(--default-padding); + margin-left: var(--inner-audit-left-padding); /* whatever the .lh-details side margins are */ width: 100%; } @@ -192,6 +382,16 @@ max-width: 70%; } +.lh-audit__stackpack { + display: flex; + align-items: center; +} + +.lh-audit__stackpack__img { + max-width: 50px; + margin-right: var(--default-padding) +} + /* Report header */ .report-icon { @@ -205,9 +405,6 @@ pointer-events: none; } -.report-icon--share { - background-image: url('data:image/svg+xml;utf8,'); -} .report-icon--print { background-image: url('data:image/svg+xml;utf8,'); } @@ -220,100 +417,116 @@ .report-icon--download { background-image: url('data:image/svg+xml;utf8,'); } +.report-icon--dark { + background-image:url('data:image/svg+xml;utf8,'); +} /* Node */ -.lh-node { - display: block; +.lh-node__snippet { font-family: var(--monospace-font-family); - word-break: break-word; - color: hsl(174, 100%, 27%); -} -.lh-node:hover { - background: hsl(0, 0%, 98%); - border-radius: 2px; + color: var(--color-teal-600); + font-size: 12px; + line-height: 1.5em; } /* Score */ .lh-audit__score-icon { - margin-left: var(--lh-score-margin); - width: var(--lh-score-icon-width); - height: var(--lh-score-icon-width); - background: none no-repeat center center / contain; + width: var(--score-shape-size); + height: var(--score-shape-size); + margin: var(--score-shape-margin); } .lh-audit--pass .lh-audit__display-text { - color: var(--pass-color); + color: var(--color-pass-secondary); } .lh-audit--pass .lh-audit__score-icon { - background-image: var(--pass-icon-url); + border-radius: 100%; + background: var(--color-pass); } .lh-audit--average .lh-audit__display-text { - color: var(--average-color); + color: var(--color-average-secondary); } .lh-audit--average .lh-audit__score-icon { - background-image: var(--average-icon-url); + background: var(--color-average); + width: var(--icon-square-size); + height: var(--icon-square-size); } .lh-audit--fail .lh-audit__display-text { - color: var(--fail-color); + color: var(--color-fail-secondary); } .lh-audit--fail .lh-audit__score-icon { - background-image: var(--fail-icon-url); + border-left: calc(var(--score-shape-size) / 2) solid transparent; + border-right: calc(var(--score-shape-size) / 2) solid transparent; + border-bottom: var(--score-shape-size) solid var(--color-fail); } -.lh-audit--informative .lh-audit__display-text { - color: var(--display-value-gray); +.lh-audit--manual .lh-audit__display-text, +.lh-audit--notapplicable .lh-audit__display-text { + color: var(--color-black-600); } - -.lh-audit--informative .lh-audit__score-icon, -.lh-audit--manual .lh-audit__score-icon { - visibility: hidden; +.lh-audit--manual .lh-audit__score-icon, +.lh-audit--notapplicable .lh-audit__score-icon { + border-radius: 100%; + background: var(--color-black-400); } + .lh-audit--error .lh-audit__score-icon { display: none; } -.lh-category-header__description, -.lh-audit__description { - color: var(--secondary-text-color); +.lh-audit--informative .lh-audit__display-text { + color: var(--color-black-600); } +.lh-audit--informative .lh-audit__score-icon { + border: none; + border-radius: 100%; + background: var(--color-black-400); +} + +.lh-audit__description, +.lh-audit__stackpack { + color: var(--secondary-text-color); +} .lh-category-header__description { font-size: var(--body-font-size); - margin: calc(var(--default-padding) / 2) 0 var(--default-padding); + text-align: center; + margin: 0px auto; + max-width: 400px; } -.lh-audit__index, -.lh-audit__title, .lh-audit__display-text, -.lh-audit__score-icon, .lh-load-opportunity__sparkline, .lh-chevron-container { margin: 0 var(--audit-item-gap); } -.lh-audit__index { - margin-left: 0; -} .lh-chevron-container { margin-right: 0; } - -.lh-audit__header .lh-audit__index { - width: var(--lh-audit-index-width); +.lh-audit__title-and-text { + flex: 1; } -.lh-audit__title { - flex: 1; +/* Prepend display text with em dash separator. But not in Opportunities. */ +.lh-audit__display-text:not(:empty):before { + content: '—'; + margin-right: var(--audit-item-gap); +} +.lh-audit-group.lh-audit-group--load-opportunities .lh-audit__display-text:not(:empty):before { + display: none; } /* Expandable Details (Audit Groups, Audits) */ .lh-audit__header { display: flex; - padding: var(--lh-audit-vpadding) var(--text-indent); + align-items: center; + font-weight: 500; + padding: var(--lh-audit-vpadding) 0; } .lh-audit--load-opportunity .lh-audit__header { @@ -321,7 +534,7 @@ } .lh-audit__header:hover { - background-color: #F8F9FA; + background-color: var(--color-hover); } /* Hide the expandable arrow icon, three ways: via the CSS Counter Styles spec, for webkit/blink browsers, hiding the polyfilled icon */ @@ -372,17 +585,25 @@ .lh-column:first-of-type { margin-right: 0px; } + .lh-column:first-of-type .lh-metric:last-of-type { + border-bottom: 0; + } } .lh-metric { border-bottom: 1px solid var(--report-secondary-border-color); } +.lh-metric:first-of-type { + border-top: 1px solid var(--report-secondary-border-color); +} .lh-metric__innerwrap { display: flex; + align-items: center; + flex-wrap: wrap; justify-content: space-between; - padding: 8px var(--text-indent); + padding: 10px 0; } .lh-metric__details { @@ -390,73 +611,131 @@ } .lh-metric__title { - font-size: var(--body-font-size); - line-height: var(--body-line-height); - display: flex; - white-space: nowrap; -} - -.lh-metric__name { flex: 1; + font-weight: 500; } .lh-metrics__disclaimer { color: var(--medium-75-gray); - text-align: right; margin: var(--lh-section-vpadding) 0; - padding: 0 var(--text-indent); } .lh-metric__description { + display: none; color: var(--secondary-text-color); + padding: var(--expandable-padding); } .lh-metric__value { white-space: nowrap; /* No wrapping between metric value and the icon */ + font-weight: 500; } +/* No-JS toggle switch */ +/* Keep this selector sync'd w/ `magicSelector` in report-ui-features-test.js */ + .lh-metrics-toggle__input:checked ~ .lh-columns .lh-metric__description { + display: block; +} -.lh-metric .lh-metric__value::after { +.lh-metrics-toggle__input { + cursor: pointer; + opacity: 0; + position: absolute; + right: 0; + width: 74px; + height: 28px; + top: -3px; +} +.lh-metrics-toggle__label { + display: flex; + background-color: #eee; + border-radius: 20px; + overflow: hidden; + position: absolute; + right: 0; + top: -3px; + pointer-events: none; +} +.lh-metrics-toggle__input:focus + label { + outline: -webkit-focus-ring-color auto 3px; +} +.lh-metrics-toggle__icon { + display: flex; + align-items: center; + justify-content: center; + padding: 2px 5px; + width: 50%; + height: 28px; +} +.lh-metrics-toggle__input:not(:checked) + label .lh-metrics-toggle__icon--less, +.lh-metrics-toggle__input:checked + label .lh-metrics-toggle__icon--more { + background-color: var(--color-blue); + --color-metric-toggle-lines: var(--color-white); +} +.lh-metrics-toggle__lines { + fill: var(--color-metric-toggle-lines); +} + +.lh-metrics-toggle__label { + background-color: var(--metrics-toggle-color); +} + +.lh-metrics-toggle__label .lh-metrics-toggle__icon--less { + padding-left: 8px; +} +.lh-metrics-toggle__label .lh-metrics-toggle__icon--more { + padding-right: 8px; +} + +/* Pushes the metric description toggle button to the right. */ +.lh-audit-group--metrics .lh-audit-group__header { + display: flex; +} +.lh-audit-group--metrics .lh-audit-group__header span.lh-audit-group__title { + flex: 1; +} + +.lh-metric .lh-metric__innerwrap::before { content: ''; - width: var(--lh-score-icon-width); - height: var(--lh-score-icon-width); - background-size: contain; + width: var(--score-shape-size); + height: var(--score-shape-size); display: inline-block; - vertical-align: text-bottom; - margin-left: calc(var(--body-font-size) / 2); + margin: var(--score-shape-margin); } .lh-metric--pass .lh-metric__value { - color: var(--pass-color); + color: var(--color-pass-secondary); } -.lh-metric--pass .lh-metric__value::after { - background: var(--pass-icon-url) no-repeat 50% 50%; +.lh-metric--pass .lh-metric__innerwrap::before { + border-radius: 100%; + background: var(--color-pass); } - .lh-metric--average .lh-metric__value { - color: var(--average-color); - padding-left: 16px; + color: var(--color-average-secondary); } -.lh-metric--average .lh-metric__value::after { - background: var(--average-icon-url) no-repeat 50% 50%; +.lh-metric--average .lh-metric__innerwrap::before { + background: var(--color-average); + width: var(--icon-square-size); + height: var(--icon-square-size); } - .lh-metric--fail .lh-metric__value { - color: var(--fail-color); + color: var(--color-fail-secondary); } -.lh-metric--fail .lh-metric__value::after { - background: var(--fail-icon-url) no-repeat 50% 50%; +.lh-metric--fail .lh-metric__innerwrap::before { + border-left: calc(var(--score-shape-size) / 2) solid transparent; + border-right: calc(var(--score-shape-size) / 2) solid transparent; + border-bottom: var(--score-shape-size) solid var(--color-fail); } .lh-metric--error .lh-metric__value, .lh-metric--error .lh-metric__description { - color: var(--fail-color); + color: var(--color-fail-secondary); } /* Hide icon if there was an error */ -.lh-metric--error .lh-metric__value::after { +.lh-metric--error .lh-metric__innerwrap::before { display: none; } @@ -468,24 +747,23 @@ } .lh-load-opportunity__header .lh-load-opportunity__col { - background-color: var(--medium-50-gray); color: var(--medium-75-gray); - text-align: center; display: unset; line-height: calc(2.3 * var(--body-font-size)); } .lh-load-opportunity__col { display: flex; - justify-content: space-between; } .lh-load-opportunity__col--one { flex: 5; + align-items: center; margin-right: 2px; } .lh-load-opportunity__col--two { flex: 4; + text-align: right; } .lh-audit--load-opportunity .lh-audit__display-text { @@ -512,15 +790,15 @@ } .lh-audit--pass .lh-sparkline__bar { - background: var(--pass-color); + background: var(--color-pass); } .lh-audit--average .lh-sparkline__bar { - background: var(--average-color); + background: var(--color-average); } .lh-audit--fail .lh-sparkline__bar { - background: var(--fail-color); + background: var(--color-fail); } @@ -528,7 +806,6 @@ /* Filmstrip */ .lh-filmstrip-container { - padding: 0 var(--expandable-indent); /* smaller gap between metrics and filmstrip */ margin: -8px auto 0 auto; } @@ -554,10 +831,14 @@ @media screen and (max-width: 750px) { .lh-filmstrip { flex-wrap: wrap; - justify-content: left; } .lh-filmstrip__frame { - margin: calc(var(--default-padding) / 3); + width: 20%; + margin-bottom: 5px; + } + .lh-filmstrip__thumbnail { + display: block; + margin: auto; } } @@ -567,80 +848,62 @@ border-bottom: 1px solid var(--report-secondary-border-color); } +/* Apply border-top to just the first audit. */ +.lh-audit { + border-top: 1px solid var(--report-secondary-border-color); +} +.lh-audit ~ .lh-audit { + border-top: none; +} + + .lh-audit--error .lh-audit__display-text { - color: var(--fail-color); + color: var(--color-fail); } /* Audit Group */ .lh-audit-group { - margin: var(--lh-audit-group-vpadding) 0; -} - -.lh-audit-group__header { - font-size: var(--subheader-font-size); - line-height: var(--subheader-line-height); - color: var(--subheader-color); - flex: 1; - font-weight: bold; + margin-bottom: var(--audits-margin-bottom); + position: relative; } .lh-audit-group__header::before { /* By default, groups don't get an icon */ content: none; - width: calc(var(--subheader-font-size) / 14 * 24); - height: calc(var(--subheader-font-size) / 14 * 24); - margin-right: calc(var(--subheader-font-size) / 2); - background: var(--medium-100-gray) none no-repeat center / 16px; + width: var(--pwa-icon-size); + height: var(--pwa-icon-size); + margin: var(--pwa-icon-margin); display: inline-block; - border-radius: 50%; vertical-align: middle; } -.lh-clump--warning > summary .lh-audit-group__header::before { - content: ''; - background-image: var(--warning-icon-url); -} -.lh-clump--manual > summary .lh-audit-group__header::before { - content: ''; - background-image: var(--search-icon-url); -} -.lh-clump--passed > summary .lh-audit-group__header::before { - content: ''; - background-image: var(--check-icon-url); -} -.lh-clump--notapplicable > summary .lh-audit-group__header::before { - content: ''; - background-image: var(--remove-circle-icon-url); +/* Style the "over budget" columns red. */ +.lh-audit-group--budgets .lh-table tbody tr td:nth-child(4), +.lh-audit-group--budgets .lh-table tbody tr td:nth-child(5){ + color: var(--color-red-700); } -.lh-audit-group--diagnostics .lh-audit-group__header::before { - content: ''; - background-image: var(--content-paste-icon-url); -} -.lh-audit-group--load-opportunities .lh-audit-group__header::before { - content: ''; - background-image: var(--photo-filter-icon-url); +/* Align the "over budget request count" text to be close to the "over budget bytes" column. */ +.lh-audit-group--budgets .lh-table tbody tr td:nth-child(4){ + text-align: right; } -.lh-audit-group--metrics .lh-audit-group__header::before { - content: ''; - background-image: var(--av-timer-icon-url); + +.lh-audit-group--budgets .lh-table { + width: 100%; } .lh-audit-group--pwa-fast-reliable .lh-audit-group__header::before { content: ''; background-image: var(--pwa-fast-reliable-gray-url); - background-size: var(--lh-group-icon-background-size); } .lh-audit-group--pwa-installable .lh-audit-group__header::before { content: ''; background-image: var(--pwa-installable-gray-url); - background-size: var(--lh-group-icon-background-size); } .lh-audit-group--pwa-optimized .lh-audit-group__header::before { content: ''; background-image: var(--pwa-optimized-gray-url); - background-size: var(--lh-group-icon-background-size); } .lh-audit-group--pwa-fast-reliable.lh-badged .lh-audit-group__header::before { background-image: var(--pwa-fast-reliable-color-url); @@ -652,11 +915,6 @@ background-image: var(--pwa-optimized-color-url); } -/* Removing too much whitespace */ -.lh-audit-group--metrics { - margin-top: calc(var(--circle-size)/2 * -1); - border-bottom: none; -} .lh-audit-group--metrics .lh-audit-group__summary { margin-top: 0; margin-bottom: 0; @@ -671,26 +929,49 @@ } .lh-audit-group__itemcount { - color: var(--display-value-gray); - margin: 3px 10px 0; + color: var(--color-black-600); + font-weight: bold; } -.lh-audit-group__summary .lh-chevron { +.lh-audit-group__header .lh-chevron { margin-top: calc((var(--body-line-height) - 5px) / 2); } -.lh-audit-group__description { +.lh-audit-group__header { font-size: var(--body-font-size); - color: var(--medium-75-gray); margin: 0 0 var(--lh-audit-group-vpadding); + /* When the header takes 100% width, the chevron becomes small. */ + max-width: calc(100% - var(--chevron-size)); +} +/* max-width makes the metric toggle not flush. metrics doesn't have a chevron so unset. */ +.lh-audit-group--metrics .lh-audit-group__header { + max-width: unset; +} + +.lh-audit-group__header span.lh-audit-group__title { + font-weight: bold; +} + +.lh-audit-group__header span.lh-audit-group__itemcount { + font-weight: bold; + color: var(--color-black-600); +} + +.lh-audit-group__header span.lh-audit-group__description { + font-weight: 500; + color: var(--color-black-600); +} +.lh-audit-group__header span.lh-audit-group__description::before { + content: '—'; + margin: 0px var(--audit-item-gap); } -.lh-clump > .lh-audit-group__description, -.lh-audit-group--diagnostics .lh-audit-group__description, -.lh-audit-group--load-opportunities .lh-audit-group__description, -.lh-audit-group--metrics .lh-audit-group__description, -.lh-audit-group--pwa-fast-reliable .lh-audit-group__description, -.lh-audit-group--pwa-installable .lh-audit-group__description, -.lh-audit-group--pwa-optimized .lh-audit-group__description { +.lh-clump > .lh-audit-group__header, +.lh-audit-group--diagnostics .lh-audit-group__header, +.lh-audit-group--load-opportunities .lh-audit-group__header, +.lh-audit-group--metrics .lh-audit-group__header, +.lh-audit-group--pwa-fast-reliable .lh-audit-group__header, +.lh-audit-group--pwa-installable .lh-audit-group__header, +.lh-audit-group--pwa-optimized .lh-audit-group__header { margin-top: var(--lh-audit-group-vpadding); } @@ -700,31 +981,10 @@ } .lh-audit--fail .lh-audit-explanation { - color: var(--fail-color); + color: var(--color-fail); } /* Report */ - -.lh-container { - display: flex; - max-width: var(--report-width); - word-wrap: break-word; - margin: 0 auto; -} - -.lh-header-sticky { - position: -webkit-sticky; - position: sticky; - top: 0; - width: 100%; - min-width: var(--report-min-width); - z-index: 2; - will-change: transform; -} -.lh-header-plain { - margin-top: var(--section-padding); -} - .lh-list > div:not(:last-child) { padding-bottom: 20px; } @@ -732,20 +992,13 @@ .lh-header-container { display: block; margin: 0 auto; - max-width: var(--report-width); position: relative; word-wrap: break-word; } .lh-report { - background-color: #fff; min-width: var(--report-min-width); } -@media screen { - .lh-report { - width: var(--report-width); - } -} .lh-exception { font-size: large; @@ -755,16 +1008,17 @@ white-space: normal; margin-top: 0; font-size: 85%; - word-break: break-word; } .lh-warnings { --item-margin: calc(var(--body-line-height) / 6); - border: 1px solid var(--average-color); - border-radius: 4px; + color: var(--color-average); margin: var(--lh-audit-vpadding) 0; padding: calc(var(--lh-audit-vpadding) / 2) var(--lh-audit-vpadding); } +.lh-warnings span { + font-weight: bold; +} .lh-warnings--toplevel { --item-margin: calc(var(--header-line-height) / 4); @@ -785,59 +1039,188 @@ .lh-scores-header { display: flex; - justify-content: left; - overflow-x: hidden; - position: relative; - padding: var(--section-indent) calc(var(--section-indent) / 2) calc(var(--section-indent) * 2); + flex-wrap: wrap; + justify-content: center; } .lh-scores-header__solo { padding: 0; border: 0; } +/* Gauge */ + +.lh-gauge__wrapper--pass { + color: var(--color-pass); + fill: var(--color-pass); + stroke: var(--color-pass); +} + +.lh-gauge__wrapper--average { + color: var(--color-average); + fill: var(--color-average); + stroke: var(--color-average); +} + +.lh-gauge__wrapper--fail { + color: var(--color-fail); + fill: var(--color-fail); + stroke: var(--color-fail); +} + +.lh-gauge { + stroke-linecap: round; + width: var(--gauge-circle-size); + height: var(--gauge-circle-size); +} + +.lh-category .lh-gauge { + --gauge-circle-size: var(--gauge-circle-size-big); +} + +.lh-gauge-base { + opacity: 0.1; + stroke: var(--circle-background); + stroke-width: var(--circle-border-width); +} + +.lh-gauge-arc { + fill: none; + stroke: var(--circle-color); + stroke-width: var(--circle-border-width); + animation: load-gauge var(--transition-length) ease forwards; + animation-delay: 250ms; +} + +.lh-gauge__svg-wrapper { + position: relative; + height: var(--gauge-circle-size); +} +.lh-category .lh-gauge__svg-wrapper { + --gauge-circle-size: var(--gauge-circle-size-big); +} + +/* The plugin badge overlay */ +.lh-gauge__wrapper--plugin .lh-gauge__svg-wrapper::before { + width: var(--plugin-badge-size); + height: var(--plugin-badge-size); + background-color: var(--plugin-badge-bg); + background-image: var(--plugin-icon-url); + background-repeat: no-repeat; + background-size: var(--plugin-icon-size); + background-position: 58% 50%; + content: ""; + position: absolute; + right: -6px; + bottom: 0px; + display: block; + z-index: 100; + box-shadow: 0 0 4px rgba(0,0,0,.2); + border-radius: 25%; +} +.lh-category .lh-gauge__wrapper--plugin .lh-gauge__svg-wrapper::before { + width: var(--plugin-badge-size-big); + height: var(--plugin-badge-size-big); +} + +@keyframes load-gauge { + from { stroke-dasharray: 0 352; } +} + +.lh-gauge__percentage { + width: 100%; + height: var(--gauge-circle-size); + position: absolute; + font-family: var(--monospace-font-family); + font-size: calc(var(--gauge-circle-size) * 0.34 + 1.3px); + line-height: 0; + text-align: center; + top: calc(var(--score-container-padding) + var(--gauge-circle-size) / 2); +} + +.lh-category .lh-gauge__percentage { + --gauge-circle-size: var(--gauge-circle-size-big); + --score-number-font-size: var(--score-number-font-size-big); +} + +.lh-gauge__wrapper { + position: relative; + display: flex; + align-items: center; + flex-direction: column; + text-decoration: none; + padding: var(--score-container-padding); + + --circle-border-width: 8; + --transition-length: 1s; + + /* Contain the layout style paint & layers during animation*/ + contain: content; + will-change: opacity; /* Only using for layer promotion */ +} + +.lh-gauge__label { + font-size: var(--score-title-font-size); + line-height: var(--score-title-line-height); + margin-top: 10px; + text-align: center; + color: var(--body-text-color); +} + +/* TODO(#8185) use more BEM (.lh-gauge__label--big) instead of relying on descendant selector */ +.lh-category .lh-gauge__label { + --score-title-font-size: var(--score-title-font-size-big); + --score-title-line-height: var(--score-title-line-height-big); + margin-top: 14px; +} + + .lh-scores-header .lh-gauge__wrapper, -.lh-scores-header .lh-gauge--pwa__wrapper { - padding: 0 4px; +.lh-scores-header .lh-gauge--pwa__wrapper, +.lh-sticky-header .lh-gauge__wrapper, +.lh-sticky-header .lh-gauge--pwa__wrapper { + width: var(--score-container-width); } .lh-scores-header .lh-gauge--pwa__wrapper { - border-left: 1px solid var(--report-secondary-border-color); /* Can remove when this bug is resolved: https://bugs.chromium.org/p/chromium/issues/detail?id=942097 */ will-change: transform; } .lh-scorescale { - color: var(--medium-75-gray); - padding: 0 calc(var(--section-indent) * 1.5) 0; - text-align: right; - transform-origin: bottom right; - will-change: opacity; /* opacity is changed on scroll */ + display: inline-flex; + margin: 12px auto 0 auto; + border: 1px solid var(--color-black-200); + border-radius: 20px; + padding: 8px 8px; } .lh-scorescale-range { - margin-left: 10px; + display: flex; + align-items: center; + margin: 0 12px; + font-family: var(--monospace-font-family); white-space: nowrap; } .lh-scorescale-range::before { content: ''; - width: var(--body-font-size); - height: calc(var(--body-font-size) * .60); - border-radius: 4px; - display: inline-block; - margin: 0 5px; + width: var(--scorescale-width); + height: var(--scorescale-height); + border-radius: 10px; + display: block; + margin-right: 10px; } .lh-scorescale-range--pass::before { - background-color: var(--pass-color); + background-color: var(--color-pass); } .lh-scorescale-range--average::before { - background-color: var(--average-color); + background-color: var(--color-average); } .lh-scorescale-range--fail::before { - background-color: var(--fail-color); + background-color: var(--color-fail); } /* Hide category score gauages if it's a single category report */ @@ -853,11 +1236,16 @@ .lh-category { padding: var(--section-padding); + max-width: var(--report-width); + margin: 0 auto; } -.lh-category:first-of-type { - padding-top: calc(2 * var(--section-padding)); - border: none; +.lh-category-wrapper { + border-bottom: 1px solid var(--color-black-200); +} + +.lh-category-wrapper:first-of-type { + border-top: 1px solid var(--color-black-200); } /* section hash link jump should preserve fixed header @@ -872,25 +1260,14 @@ .lh-category-header { font-size: var(--header-font-size); - min-height: var(--circle-size); + min-height: var(--gauge-circle-size); margin-bottom: var(--lh-section-vpadding); } -.lh-category-header__title { - line-height: 24px; -} - -.lh-category-header .lh-score__gauge .lh-gauge__label { - display: none; -} - - .lh-category-header .lh-score__gauge { - float: right; -} - -.lh-category-header .lh-score__gauge { - margin-left: var(--section-indent); + max-width: 400px; + width: auto; + margin: 0px auto; } .lh-category-header .lh-audit__title { @@ -913,7 +1290,6 @@ transition: transform 0.3s, opacity 0.3s; transform: translateY(100px); opacity: 0; - -webkit-font-smoothing: antialiased; bottom: 0; left: 0; z-index: 3; @@ -951,18 +1327,18 @@ .lh-table { --image-preview-size: 24px; border-collapse: collapse; + /* Can't assign padding to table, so shorten the width instead. */ + width: calc(100% - var(--inner-audit-left-padding)); } -.lh-table thead { - background: var(--lh-table-header-bg); -} .lh-table thead th { - color: var(--medium-75-gray); font-weight: normal; - word-wrap: normal; + color: var(--color-black-600); + /* See text-wrapping comment on .lh-container. */ + word-break: normal; } -.lh-table tbody tr:nth-child(even) { +.lh-table tbody tr:nth-child(odd) { background-color: var(--lh-table-higlight-bg); } @@ -970,6 +1346,12 @@ .lh-table td { padding: 8px 6px; } +.lh-table th:first-child { + padding-left: 0; +} +.lh-table th:last-child { + padding-right: 0; +} /* Looks unnecessary, but mostly for keeping the s left-aligned */ .lh-table-column--text, @@ -986,6 +1368,7 @@ .lh-table-column--ms, .lh-table-column--numeric { text-align: right; + word-break: normal; } @@ -995,7 +1378,6 @@ .lh-table-column--url { min-width: 250px; - white-space: nowrap; } /* Keep columns narrow if they follow the URL column */ @@ -1008,18 +1390,13 @@ width: 12%; } -.lh-text__url { - overflow: hidden; - text-overflow: ellipsis; -} - .lh-text__url:hover { text-decoration: underline dotted #999; text-decoration-skip-ink: auto; } .lh-text__url > .lh-text, .lh-text__url-host { - display: inline-block; + display: inline; } .lh-text__url-host { @@ -1105,7 +1482,7 @@ } .tooltip-boundary:hover { - background-color: #F8F9FA; + background-color: var(--color-hover); } .tooltip-boundary:hover .tooltip { diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.js index c9371afee5f..e4c246548e8 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report.js @@ -16,11 +16,12 @@ */ 'use strict'; -/* globals self URL */ +/* globals self, URL */ const ELLIPSIS = '\u2026'; const NBSP = '\xa0'; const PASS_THRESHOLD = 0.9; +const SCREENSHOT_PREFIX = 'data:image/jpeg;base64,'; const RATINGS = { PASS: {label: 'pass', minScore: PASS_THRESHOLD}, @@ -29,6 +30,14 @@ const RATINGS = { ERROR: {label: 'error'}, }; +// 25 most used tld plus one domains (aka public suffixes) from http archive. +// @see https://github.com/GoogleChrome/lighthouse/pull/5065#discussion_r191926212 +// The canonical list is https://publicsuffix.org/learn/ but we're only using subset to conserve bytes +const listOfTlds = [ + 'com', 'co', 'gov', 'edu', 'ac', 'org', 'go', 'gob', 'or', 'net', 'in', 'ne', 'nic', 'gouv', + 'web', 'spb', 'blog', 'jus', 'kiev', 'mil', 'wi', 'qc', 'ca', 'bel', 'on', +]; + class Util { static get PASS_THRESHOLD() { return PASS_THRESHOLD; @@ -40,7 +49,8 @@ class Util { /** * Returns a new LHR that's reshaped for slightly better ergonomics within the report rendereer. - * Also, sets up the localized UI strings used within renderer and number/date formatting + * Also, sets up the localized UI strings used within renderer and makes changes to old LHRs to be + * compatible with current renderer. * The LHR passed in is not mutated. * TODO(team): we all agree the LHR shape change is technical debt we should fix * @param {LH.Result} result @@ -50,33 +60,65 @@ class Util { // If any mutations happen to the report within the renderers, we want the original object untouched const clone = /** @type {LH.ReportResult} */ (JSON.parse(JSON.stringify(result))); - // If LHR is older (\\u22643.0.3), it has no locale setting. Set default. + // If LHR is older (≤3.0.3), it has no locale setting. Set default. if (!clone.configSettings.locale) { clone.configSettings.locale = 'en'; } - Util.setNumberDateLocale(clone.configSettings.locale); - if (clone.i18n && clone.i18n.rendererFormattedStrings) { - Util.updateAllUIStrings(clone.i18n.rendererFormattedStrings); - } - - if (typeof clone.categories !== 'object') throw new Error('No categories provided.'); - clone.reportCategories = Object.values(clone.categories); - // Turn 'not-applicable' and 'not_applicable' into 'notApplicable' to support old reports. - // TODO: remove when underscore/hyphen proto issue is resolved. See #6371, #6201, #6783. for (const audit of Object.values(clone.audits)) { - // @ts-ignore tsc rightly flags that this value shouldn't occur. + // Turn 'not-applicable' (LHR <4.0) and 'not_applicable' (older proto versions) + // into 'notApplicable' (LHR ≥4.0). + // @ts-ignore tsc rightly flags that these values shouldn't occur. // eslint-disable-next-line max-len if (audit.scoreDisplayMode === 'not_applicable' || audit.scoreDisplayMode === 'not-applicable') { audit.scoreDisplayMode = 'notApplicable'; } + + if (audit.details) { + // Turn `auditDetails.type` of undefined (LHR <4.2) and 'diagnostic' (LHR <5.0) + // into 'debugdata' (LHR ≥5.0). + // @ts-ignore tsc rightly flags that these values shouldn't occur. + if (audit.details.type === undefined || audit.details.type === 'diagnostic') { + audit.details.type = 'debugdata'; + } + + // Add the jpg data URL prefix to filmstrip screenshots without them (LHR <5.0). + if (audit.details.type === 'filmstrip') { + for (const screenshot of audit.details.items) { + if (!screenshot.data.startsWith(SCREENSHOT_PREFIX)) { + screenshot.data = SCREENSHOT_PREFIX + screenshot.data; + } + } + } + } + } + + // Set locale for number/date formatting and grab localized renderer strings from the LHR. + Util.setNumberDateLocale(clone.configSettings.locale); + if (clone.i18n && clone.i18n.rendererFormattedStrings) { + Util.updateAllUIStrings(clone.i18n.rendererFormattedStrings); } - // For convenience, smoosh all AuditResults into their auditDfn (which has just weight & group) - for (const category of clone.reportCategories) { - category.auditRefs.forEach(auditMeta => { - const result = clone.audits[auditMeta.id]; - auditMeta.result = result; + // For convenience, smoosh all AuditResults into their auditRef (which has just weight & group) + if (typeof clone.categories !== 'object') throw new Error('No categories provided.'); + for (const category of Object.values(clone.categories)) { + category.auditRefs.forEach(auditRef => { + const result = clone.audits[auditRef.id]; + auditRef.result = result; + + // attach the stackpacks to the auditRef object + if (clone.stackPacks) { + clone.stackPacks.forEach(pack => { + if (pack.descriptions[auditRef.id]) { + auditRef.stackPacks = auditRef.stackPacks || []; + auditRef.stackPacks.push({ + title: pack.title, + iconDataURL: pack.iconDataURL, + description: pack.descriptions[auditRef.id], + }); + } + }); + } }); } @@ -322,6 +364,51 @@ class Util { }; } + /** + * @param {string|URL} value + * @return {URL} + */ + static createOrReturnURL(value) { + if (value instanceof URL) { + return value; + } + + return new URL(value); + } + + /** + * Gets the tld of a domain + * + * @param {string} hostname + * @return {string} tld + */ + static getTld(hostname) { + const tlds = hostname.split('.').slice(-2); + + if (!listOfTlds.includes(tlds[0])) { + return `.${tlds[tlds.length - 1]}`; + } + + return `.${tlds.join('.')}`; + } + + /** + * Returns a primary domain for provided hostname (e.g. www.example.com -> example.com). + * @param {string|URL} url hostname or URL object + * @returns {string} + */ + static getRootDomain(url) { + const hostname = Util.createOrReturnURL(url).hostname; + const tld = Util.getTld(hostname); + + // tld is .com or .co.uk which means we means that length is 1 to big + // .com => 2 & .co.uk => 3 + const splitTld = tld.split('.'); + + // get TLD + root domain + return hostname.split('.').slice(-splitTld.length).join('.'); + } + /** * @param {LH.Config.Settings} settings * @return {Array<{name: string, description: string}>} @@ -386,10 +473,8 @@ class Util { } let deviceEmulation = 'No emulation'; - if (!settings.disableDeviceEmulation) { - if (settings.emulatedFormFactor === 'mobile') deviceEmulation = 'Emulated Nexus 5X'; - if (settings.emulatedFormFactor === 'desktop') deviceEmulation = 'Emulated Desktop'; - } + if (settings.emulatedFormFactor === 'mobile') deviceEmulation = 'Emulated Nexus 5X'; + if (settings.emulatedFormFactor === 'desktop') deviceEmulation = 'Emulated Desktop'; return { deviceEmulation, @@ -451,6 +536,13 @@ class Util { return lines.filter(line => lineNumbersToKeep.has(line.lineNumber)); } + + /** + * @param {string} categoryId + */ + static isPluginCategory(categoryId) { + return categoryId.startsWith('lighthouse-plugin-'); + } } /** @@ -490,8 +582,6 @@ Util.UIStrings = { /** Label shown preceding any important warnings that may have invalidated the entire report. For example, if the user has Chrome extensions installed, they may add enough performance overhead that Lighthouse's performance metrics are unreliable. If shown, this will be displayed at the top of the report UI. */ toplevelWarningsMessage: 'There were issues affecting this run of Lighthouse:', - /** Label preceding a pictorial explanation of the scoring scale: 0-50 is red (bad), 50-90 is orange (ok), 90-100 is green (good). These colors are used throughout the report to provide context for how good/bad a particular result is. */ - scorescaleLabel: 'Score scale:', /** String of text shown in a graphical representation of the flow of network requests for the web page. This label represents the initial network request that fetches an HTML page. This navigation may be redirected (eg. Initial navigation to http://example.com redirects to https://www.example.com). */ crcInitialNavigation: 'Initial Navigation', @@ -507,6 +597,9 @@ Util.UIStrings = { lsPerformanceCategoryDescription: '[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary.', /** Title of the lab data section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds. "Lab" is an abbreviated form of "laboratory", and refers to the fact that the data is from a controlled test of a website, not measurements from real users visiting that site. */ labDataTitle: 'Lab Data', + + /** This label is for a checkbox above a table of items loaded by a web page. The checkbox is used to show or hide third-party (or "3rd-party") resources in the table, where "third-party resources" refers to items loaded by a web page from URLs that aren't controlled by the owner of the web page. */ + thirdPartyResourcesLabel: 'Show 3rd-party resources', }; if (typeof module !== 'undefined' && module.exports) { @@ -744,7 +837,7 @@ if (typeof module !== 'undefined' && module.exports) { ; /* Details Element Polyfill 2.2.0 -Copyright \\ua9 2018 Javan Makhmali +Copyright © 2018 Javan Makhmali */ (function() { "use strict"; @@ -763,7 +856,7 @@ Copyright \\ua9 2018 Javan Makhmali element.parentNode.removeChild(element); return closedHeight != openedHeight; } - var styles = '\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\ndetails > summary::before {\n content: "\\u25ba";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\ndetails[open] > summary::before {\n content: "\\u25bc";\n}\n'; + var styles = '\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\ndetails > summary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\ndetails[open] > summary::before {\n content: "▼";\n}\n'; var _ref = [], forEach = _ref.forEach, slice = _ref.slice; if (!support.open) { polyfillStyles(); @@ -1007,10 +1100,7 @@ class DetailsRenderer { // Internal-only details, not for rendering. case 'screenshot': - case 'diagnostic': - return null; - // Fallback for old LHRs, where no type meant don't render. - case undefined: + case 'debugdata': return null; default: { @@ -1072,7 +1162,11 @@ class DetailsRenderer { element.appendChild(hostElem); } - if (title) element.title = url; + if (title) { + element.title = url; + // set the url on the element's dataset which we use to check 3rd party origins + element.dataset.url = url; + } return element; } @@ -1279,7 +1373,7 @@ class DetailsRenderer { /** * @param {LH.Audit.Details.List} details - * @returns {Element} + * @return {Element} */ _renderList(details) { const listContainer = this._dom.createElement('div', 'lh-list'); @@ -1299,8 +1393,16 @@ class DetailsRenderer { */ renderNode(item) { const element = this._dom.createElement('span', 'lh-node'); + if (item.nodeLabel) { + const nodeLabelEl = this._dom.createElement('div'); + nodeLabelEl.textContent = item.nodeLabel; + element.appendChild(nodeLabelEl); + } if (item.snippet) { - element.textContent = item.snippet; + const snippetEl = this._dom.createElement('div'); + snippetEl.classList.add('lh-node__snippet'); + snippetEl.textContent = item.snippet; + element.appendChild(snippetEl); } if (item.selector) { element.title = item.selector; @@ -1308,6 +1410,7 @@ class DetailsRenderer { if (item.path) element.setAttribute('data-path', item.path); if (item.selector) element.setAttribute('data-selector', item.selector); if (item.snippet) element.setAttribute('data-snippet', item.snippet); + return element; } @@ -1321,7 +1424,7 @@ class DetailsRenderer { for (const thumbnail of details.items) { const frameEl = this._dom.createChildOf(filmstripEl, 'div', 'lh-filmstrip__frame'); this._dom.createChildOf(frameEl, 'img', 'lh-filmstrip__thumbnail', { - src: `data:image/jpeg;base64,${thumbnail.data}`, + src: thumbnail.data, alt: `Screenshot`, }); } @@ -1622,7 +1725,7 @@ function getMessagesForLineNumber(messages, lineNumber) { /** * @param {LH.Audit.Details.SnippetValue} details - * @returns {LH.Audit.Details.SnippetValue['lines']} + * @return {LH.Audit.Details.SnippetValue['lines']} */ function getLinesWhenCollapsed(details) { const SURROUNDING_LINES_TO_SHOW_WHEN_COLLAPSED = 2; @@ -1714,7 +1817,7 @@ class SnippetRenderer { classList.add('lh-snippet__show-if-expanded'); } - const lineContent = content + (truncated ? '\\u2026' : ''); + const lineContent = content + (truncated ? '…' : ''); const lineContentEl = dom.find('.lh-snippet__line code', contentLine); if (contentType === LineContentType.MESSAGE) { lineContentEl.appendChild(dom.convertMarkdownLinkSnippets(lineContent)); @@ -1752,7 +1855,7 @@ class SnippetRenderer { */ static renderOmittedLinesPlaceholder(dom, tmpl, visibility) { return SnippetRenderer.renderSnippetLine(dom, tmpl, { - lineNumber: '\\u2026', + lineNumber: '…', content: '', visibility, contentType: LineContentType.PLACEHOLDER, @@ -1783,7 +1886,7 @@ class SnippetRenderer { * @param {DOM} dom * @param {DocumentFragment} tmpl * @param {LH.Audit.Details.SnippetValue} details - * @returns {DocumentFragment} + * @return {DocumentFragment} */ static renderSnippetLines(dom, tmpl, details) { const {lineMessages, generalMessages, lineCount, lines} = details; @@ -1938,7 +2041,7 @@ if (typeof module !== 'undefined' && module.exports) { * @return {string} */ function getFilenamePrefix(lhr) { - const hostname = new (getUrlConstructor())(lhr.finalUrl).hostname; + const hostname = new URL(lhr.finalUrl).hostname; const date = (lhr.fetchTime && new Date(lhr.fetchTime)) || new Date(); const timeStr = date.toLocaleTimeString('en-US', {hour12: false}); @@ -1954,14 +2057,6 @@ function getFilenamePrefix(lhr) { return filenamePrefix.replace(/[/?<>\\:*|":]/g, '-'); } -function getUrlConstructor() { - if (typeof module !== 'undefined' && module.exports) { - return require('./url-shim'); - } else { - return URL; - } -} - // don't attempt to export in the browser. if (typeof module !== 'undefined' && module.exports) { module.exports = {getFilenamePrefix}; @@ -2067,6 +2162,656 @@ if (typeof module !== 'undefined' && module.exports) { */ 'use strict'; +/* eslint-env browser */ + +/** + * @fileoverview Adds export button, print, and other dynamic functionality to + * the report. + */ + +/* globals getFilenamePrefix Util */ + +/** + * @param {HTMLTableElement} tableEl + * @return {Array} + */ +function getTableRows(tableEl) { + return Array.from(tableEl.tBodies[0].rows); +} + +class ReportUIFeatures { + /** + * @param {DOM} dom + */ + constructor(dom) { + /** @type {LH.Result} */ + this.json; // eslint-disable-line no-unused-expressions + /** @type {DOM} */ + this._dom = dom; + /** @type {Document} */ + this._document = this._dom.document(); + /** @type {ParentNode} */ + this._templateContext = this._dom.document(); + /** @type {boolean} */ + this._copyAttempt = false; + /** @type {HTMLElement} */ + this.exportButton; // eslint-disable-line no-unused-expressions + /** @type {HTMLElement} */ + this.topbarEl; // eslint-disable-line no-unused-expressions + /** @type {HTMLElement} */ + this.scoreScaleEl; // eslint-disable-line no-unused-expressions + /** @type {HTMLElement} */ + this.stickyHeaderEl; // eslint-disable-line no-unused-expressions + /** @type {HTMLElement} */ + this.highlightEl; // eslint-disable-line no-unused-expressions + + this.onMediaQueryChange = this.onMediaQueryChange.bind(this); + this.onCopy = this.onCopy.bind(this); + this.onExportButtonClick = this.onExportButtonClick.bind(this); + this.onExport = this.onExport.bind(this); + this.onKeyDown = this.onKeyDown.bind(this); + this.onKeyUp = this.onKeyUp.bind(this); + this.onChevronClick = this.onChevronClick.bind(this); + this.collapseAllDetails = this.collapseAllDetails.bind(this); + this.expandAllDetails = this.expandAllDetails.bind(this); + this._toggleDarkTheme = this._toggleDarkTheme.bind(this); + this._updateStickyHeaderOnScroll = this._updateStickyHeaderOnScroll.bind(this); + } + + /** + * Adds export button, print, and other functionality to the report. The method + * should be called whenever the report needs to be re-rendered. + * @param {LH.Result} report + */ + initFeatures(report) { + this.json = report; + + this._setupMediaQueryListeners(); + this._setupExportButton(); + this._setupThirdPartyFilter(); + this._setUpCollapseDetailsAfterPrinting(); + this._resetUIState(); + this._document.addEventListener('keyup', this.onKeyUp); + this._document.addEventListener('copy', this.onCopy); + + const topbarLogo = this._dom.find('.lh-topbar__logo', this._document); + topbarLogo.addEventListener('click', () => this._toggleDarkTheme()); + + let turnOffTheLights = false; + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + turnOffTheLights = true; + } + + // Fireworks. + const scoresAll100 = Object.values(report.categories).every(cat => cat.score === 1); + const hasAllCoreCategories = + Object.keys(report.categories).filter(id => !Util.isPluginCategory(id)).length >= 5; + if (scoresAll100 && hasAllCoreCategories) { + turnOffTheLights = true; + this._enableFireworks(); + } + + if (turnOffTheLights) { + this._toggleDarkTheme(true); + } + + // There is only a sticky header when at least 2 categories are present. + if (Object.keys(this.json.categories).length >= 2) { + this._setupStickyHeaderElements(); + const containerEl = this._dom.find('.lh-container', this._document); + const elToAddScrollListener = this._getScrollParent(containerEl); + elToAddScrollListener.addEventListener('scroll', this._updateStickyHeaderOnScroll); + + // Use ResizeObserver where available. + // TODO: there is an issue with incorrect position numbers and, as a result, performance + // issues due to layout thrashing. + // See https://github.com/GoogleChrome/lighthouse/pull/9023/files#r288822287 for details. + // For now, limit to DevTools. + if (this._dom.isDevTools()) { + const resizeObserver = new window.ResizeObserver(this._updateStickyHeaderOnScroll); + resizeObserver.observe(containerEl); + } else { + window.addEventListener('resize', this._updateStickyHeaderOnScroll); + } + } + + // Show the metric descriptions by default when there is an error. + const hasMetricError = report.categories.performance && report.categories.performance.auditRefs + .some(audit => Boolean(audit.group === 'metrics' && report.audits[audit.id].errorMessage)); + if (hasMetricError) { + const toggleInputEl = /** @type {HTMLInputElement} */ ( + this._dom.find('.lh-metrics-toggle__input', this._document)); + toggleInputEl.checked = true; + } + } + + /** + * Define a custom element for to be extracted from. For example: + * this.setTemplateContext(new DOMParser().parseFromString(htmlStr, 'text/html')) + * @param {ParentNode} context + */ + setTemplateContext(context) { + this._templateContext = context; + } + + /** + * Finds the first scrollable ancestor of `element`. Falls back to the document. + * @param {HTMLElement} element + * @return {Node} + */ + _getScrollParent(element) { + const {overflowY} = window.getComputedStyle(element); + const isScrollable = overflowY !== 'visible' && overflowY !== 'hidden'; + + if (isScrollable) { + return element; + } + + if (element.parentElement) { + return this._getScrollParent(element.parentElement); + } + + return document; + } + + _enableFireworks() { + const scoresContainer = this._dom.find('.lh-scores-container', this._document); + scoresContainer.classList.add('score100'); + scoresContainer.addEventListener('click', _ => { + scoresContainer.classList.toggle('fireworks-paused'); + }); + } + + /** + * Fires a custom DOM event on target. + * @param {string} name Name of the event. + * @param {Node=} target DOM node to fire the event on. + * @param {*=} detail Custom data to include. + */ + _fireEventOn(name, target = this._document, detail) { + const event = new CustomEvent(name, detail ? {detail} : undefined); + target.dispatchEvent(event); + } + + _setupMediaQueryListeners() { + const mediaQuery = self.matchMedia('(max-width: 500px)'); + mediaQuery.addListener(this.onMediaQueryChange); + // Ensure the handler is called on init + this.onMediaQueryChange(mediaQuery); + } + + /** + * Handle media query change events. + * @param {MediaQueryList|MediaQueryListEvent} mql + */ + onMediaQueryChange(mql) { + const root = this._dom.find('.lh-root', this._document); + root.classList.toggle('lh-narrow', mql.matches); + } + + _setupExportButton() { + this.exportButton = this._dom.find('.lh-export__button', this._document); + this.exportButton.addEventListener('click', this.onExportButtonClick); + + const dropdown = this._dom.find('.lh-export__dropdown', this._document); + dropdown.addEventListener('click', this.onExport); + } + + _setupThirdPartyFilter() { + // Some audits should not display the third party filter option. + const thirdPartyFilterAuditExclusions = [ + // This audit deals explicitly with third party resources. + 'uses-rel-preconnect', + ]; + + // Get all tables with a text url column. + /** @type {Array} */ + const tables = Array.from(this._document.querySelectorAll('.lh-table')); + const tablesWithUrls = tables + .filter(el => el.querySelector('td.lh-table-column--url')) + .filter(el => { + const containingAudit = el.closest('.lh-audit'); + if (!containingAudit) throw new Error('.lh-table not within audit'); + return !thirdPartyFilterAuditExclusions.includes(containingAudit.id); + }); + + tablesWithUrls.forEach((tableEl, index) => { + const urlItems = this._getUrlItems(tableEl); + const thirdPartyRows = this._getThirdPartyRows(tableEl, urlItems, this.json.finalUrl); + // If all or none of the rows are 3rd party, no checkbox! + if (thirdPartyRows.size === urlItems.length || !thirdPartyRows.size) return; + + // create input box + const filterTemplate = this._dom.cloneTemplate('#tmpl-lh-3p-filter', this._templateContext); + const filterInput = this._dom.find('input', filterTemplate); + const id = `lh-3p-filter-label--${index}`; + + filterInput.id = id; + filterInput.addEventListener('change', e => { + // Remove rows from the dom and keep track of them to re-add on uncheck. + // Why removing instead of hiding? To keep nth-child(even) background-colors working. + if (e.target instanceof HTMLInputElement && !e.target.checked) { + for (const row of thirdPartyRows.values()) { + row.remove(); + } + } else { + // Add row elements back to original positions. + for (const [position, row] of thirdPartyRows.entries()) { + const childrenArr = getTableRows(tableEl); + tableEl.tBodies[0].insertBefore(row, childrenArr[position]); + } + } + }); + + this._dom.find('label', filterTemplate).setAttribute('for', id); + this._dom.find('.lh-3p-filter-count', filterTemplate).textContent = + `${thirdPartyRows.size}`; + this._dom.find('.lh-3p-ui-string', filterTemplate).textContent = + Util.UIStrings.thirdPartyResourcesLabel; + + // Finally, add checkbox to the DOM. + if (!tableEl.parentNode) return; // Keep tsc happy. + tableEl.parentNode.insertBefore(filterTemplate, tableEl); + }); + } + + /** + * From a table with URL entries, finds the rows containing third-party URLs + * and returns a Map of those rows, mapping from row index to row Element. + * @param {HTMLTableElement} el + * @param {string} finalUrl + * @param {Array} urlItems + * @return {Map} + */ + _getThirdPartyRows(el, urlItems, finalUrl) { + const finalUrlRootDomain = Util.getRootDomain(finalUrl); + + /** @type {Map} */ + const thirdPartyRows = new Map(); + for (const urlItem of urlItems) { + const datasetUrl = urlItem.dataset.url; + if (!datasetUrl) continue; + const isThirdParty = Util.getRootDomain(datasetUrl) !== finalUrlRootDomain; + if (!isThirdParty) continue; + + const urlRowEl = urlItem.closest('tr'); + if (urlRowEl) { + const rowPosition = getTableRows(el).indexOf(urlRowEl); + thirdPartyRows.set(rowPosition, urlRowEl); + } + } + + return thirdPartyRows; + } + + /** + * From a table, finds and returns URL items. + * @param {HTMLTableElement} tableEl + * @return {Array} + */ + _getUrlItems(tableEl) { + return this._dom.findAll('.lh-text__url', tableEl); + } + + _setupStickyHeaderElements() { + this.topbarEl = this._dom.find('.lh-topbar', this._document); + this.scoreScaleEl = this._dom.find('.lh-scorescale', this._document); + this.stickyHeaderEl = this._dom.find('.lh-sticky-header', this._document); + + // Position highlighter at first gauge; will be transformed on scroll. + const firstGauge = this._dom.find('.lh-gauge__wrapper', this.stickyHeaderEl); + this.highlightEl = this._dom.createChildOf(firstGauge, 'div', 'lh-highlighter'); + } + + /** + * Handle copy events. + * @param {ClipboardEvent} e + */ + onCopy(e) { + // Only handle copy button presses (e.g. ignore the user copying page text). + if (this._copyAttempt) { + // We want to write our own data to the clipboard, not the user's text selection. + e.preventDefault(); + e.clipboardData.setData('text/plain', JSON.stringify(this.json, null, 2)); + + this._fireEventOn('lh-log', this._document, { + cmd: 'log', msg: 'Report JSON copied to clipboard', + }); + } + + this._copyAttempt = false; + } + + /** + * Copies the report JSON to the clipboard (if supported by the browser). + */ + onCopyButtonClick() { + this._fireEventOn('lh-analytics', this._document, { + cmd: 'send', + fields: {hitType: 'event', eventCategory: 'report', eventAction: 'copy'}, + }); + + try { + if (this._document.queryCommandSupported('copy')) { + this._copyAttempt = true; + + // Note: In Safari 10.0.1, execCommand('copy') returns true if there's + // a valid text selection on the page. See http://caniuse.com/#feat=clipboard. + if (!this._document.execCommand('copy')) { + this._copyAttempt = false; // Prevent event handler from seeing this as a copy attempt. + + this._fireEventOn('lh-log', this._document, { + cmd: 'warn', msg: 'Your browser does not support copy to clipboard.', + }); + } + } + } catch (/** @type {Error} */ e) { + this._copyAttempt = false; + this._fireEventOn('lh-log', this._document, {cmd: 'log', msg: e.message}); + } + } + + onChevronClick() { + const toggle = this._dom.find('.lh-config__settings-toggle', this._document); + + if (toggle.hasAttribute('open')) { + toggle.removeAttribute('open'); + } else { + toggle.setAttribute('open', 'true'); + } + } + + closeExportDropdown() { + this.exportButton.classList.remove('active'); + } + + /** + * Click handler for export button. + * @param {Event} e + */ + onExportButtonClick(e) { + e.preventDefault(); + this.exportButton.classList.toggle('active'); + this._document.addEventListener('keydown', this.onKeyDown); + } + + /** + * Resets the state of page before capturing the page for export. + * When the user opens the exported HTML page, certain UI elements should + * be in their closed state (not opened) and the templates should be unstamped. + */ + _resetUIState() { + this.closeExportDropdown(); + this._dom.resetTemplates(); + } + + /** + * Handler for "export as" button. + * @param {Event} e + */ + onExport(e) { + e.preventDefault(); + + const el = /** @type {?Element} */ (e.target); + + if (!el || !el.hasAttribute('data-action')) { + return; + } + + switch (el.getAttribute('data-action')) { + case 'copy': + this.onCopyButtonClick(); + break; + case 'print-summary': + this.collapseAllDetails(); + this.closeExportDropdown(); + self.print(); + break; + case 'print-expanded': + this.expandAllDetails(); + this.closeExportDropdown(); + self.print(); + break; + case 'save-json': { + const jsonStr = JSON.stringify(this.json, null, 2); + this._saveFile(new Blob([jsonStr], {type: 'application/json'})); + break; + } + case 'save-html': { + const htmlStr = this.getReportHtml(); + try { + this._saveFile(new Blob([htmlStr], {type: 'text/html'})); + } catch (/** @type {Error} */ e) { + this._fireEventOn('lh-log', this._document, { + cmd: 'error', msg: 'Could not export as HTML. ' + e.message, + }); + } + break; + } + case 'open-viewer': { + const viewerPath = '/lighthouse/viewer/'; + ReportUIFeatures.openTabAndSendJsonReport(this.json, viewerPath); + break; + } + case 'save-gist': { + this.saveAsGist(); + break; + } + case 'toggle-dark': { + this._toggleDarkTheme(); + break; + } + } + + this.closeExportDropdown(); + this._document.removeEventListener('keydown', this.onKeyDown); + } + + /** + * Keydown handler for the document. + * @param {KeyboardEvent} e + */ + onKeyDown(e) { + if (e.keyCode === 27) { // ESC + this.closeExportDropdown(); + } + } + + /** + * Keyup handler for the document. + * @param {KeyboardEvent} e + */ + onKeyUp(e) { + // Ctrl+P - Expands audit details when user prints via keyboard shortcut. + if ((e.ctrlKey || e.metaKey) && e.keyCode === 80) { + this.closeExportDropdown(); + } + } + + /** + * Opens a new tab to the online viewer and sends the local page's JSON results + * to the online viewer using postMessage. + * @param {LH.Result} reportJson + * @param {string} viewerPath + * @protected + */ + static openTabAndSendJsonReport(reportJson, viewerPath) { + const VIEWER_ORIGIN = 'https://googlechrome.github.io'; + // Chrome doesn't allow us to immediately postMessage to a popup right + // after it's created. Normally, we could also listen for the popup window's + // load event, however it is cross-domain and won't fire. Instead, listen + // for a message from the target app saying "I'm open". + const json = reportJson; + window.addEventListener('message', function msgHandler(messageEvent) { + if (messageEvent.origin !== VIEWER_ORIGIN) { + return; + } + if (popup && messageEvent.data.opened) { + popup.postMessage({lhresults: json}, VIEWER_ORIGIN); + window.removeEventListener('message', msgHandler); + } + }); + + // The popup's window.name is keyed by version+url+fetchTime, so we reuse/select tabs correctly + // @ts-ignore - If this is a v2 LHR, use old `generatedTime`. + const fallbackFetchTime = /** @type {string} */ (json.generatedTime); + const fetchTime = json.fetchTime || fallbackFetchTime; + const windowName = `${json.lighthouseVersion}-${json.requestedUrl}-${fetchTime}`; + const popup = window.open(`${VIEWER_ORIGIN}${viewerPath}`, windowName); + } + + /** + * Expands all audit `
`. + * Ideally, a print stylesheet could take care of this, but CSS has no way to + * open a `
` element. + */ + expandAllDetails() { + const details = /** @type {Array} */ (this._dom.findAll( + '.lh-categories details', this._document)); + details.map(detail => detail.open = true); + } + + /** + * Collapses all audit `
`. + * open a `
` element. + */ + collapseAllDetails() { + const details = /** @type {Array} */ (this._dom.findAll( + '.lh-categories details', this._document)); + details.map(detail => detail.open = false); + } + + /** + * Sets up listeners to collapse audit `
` when the user closes the + * print dialog, all `
` are collapsed. + */ + _setUpCollapseDetailsAfterPrinting() { + // FF and IE implement these old events. + if ('onbeforeprint' in self) { + self.addEventListener('afterprint', this.collapseAllDetails); + } else { + const win = /** @type {Window} */ (self); + // Note: FF implements both window.onbeforeprint and media listeners. However, + // it doesn't matchMedia doesn't fire when matching 'print'. + win.matchMedia('print').addListener(mql => { + if (mql.matches) { + this.expandAllDetails(); + } else { + this.collapseAllDetails(); + } + }); + } + } + + /** + * Returns the html that recreates this report. + * @return {string} + * @protected + */ + getReportHtml() { + this._resetUIState(); + return this._document.documentElement.outerHTML; + } + + /** + * Save json as a gist. Unimplemented in base UI features. + * @protected + */ + saveAsGist() { + throw new Error('Cannot save as gist from base report'); + } + + /** + * Downloads a file (blob) using a[download]. + * @param {Blob|File} blob The file to save. + * @private + */ + _saveFile(blob) { + const filename = getFilenamePrefix({ + finalUrl: this.json.finalUrl, + fetchTime: this.json.fetchTime, + }); + + const ext = blob.type.match('json') ? '.json' : '.html'; + const href = URL.createObjectURL(blob); + + const a = this._dom.createElement('a'); + a.download = `${filename}${ext}`; + a.href = href; + this._document.body.appendChild(a); // Firefox requires anchor to be in the DOM. + a.click(); + + // cleanup. + this._document.body.removeChild(a); + setTimeout(_ => URL.revokeObjectURL(href), 500); + } + + /** + * @private + * @param {boolean} [force] + */ + _toggleDarkTheme(force) { + const el = this._dom.find('.lh-vars', this._document); + // This seems unnecessary, but in DevTools, passing "undefined" as the second + // parameter acts like passing "false". + // https://github.com/ChromeDevTools/devtools-frontend/blob/dd6a6d4153647c2a4203c327c595692c5e0a4256/front_end/dom_extension/DOMExtension.js#L809-L819 + if (typeof force === 'undefined') { + el.classList.toggle('dark'); + } else { + el.classList.toggle('dark', force); + } + } + + _updateStickyHeaderOnScroll() { + // Show sticky header when the score scale begins to go underneath the topbar. + const topbarBottom = this.topbarEl.getBoundingClientRect().bottom; + const scoreScaleTop = this.scoreScaleEl.getBoundingClientRect().top; + const showStickyHeader = topbarBottom >= scoreScaleTop; + + // Highlight mini gauge when section is in view. + // In view = the last category that starts above the middle of the window. + const categoryEls = Array.from(this._document.querySelectorAll('.lh-category')); + const categoriesAboveTheMiddle = + categoryEls.filter(el => el.getBoundingClientRect().top - window.innerHeight / 2 < 0); + const highlightIndex = + categoriesAboveTheMiddle.length > 0 ? categoriesAboveTheMiddle.length - 1 : 0; + + // Category order matches gauge order in sticky header. + const gaugeWrapperEls = this.stickyHeaderEl.querySelectorAll('.lh-gauge__wrapper'); + const gaugeToHighlight = gaugeWrapperEls[highlightIndex]; + const origin = gaugeWrapperEls[0].getBoundingClientRect().left; + const offset = gaugeToHighlight.getBoundingClientRect().left - origin; + + // Mutate at end to avoid layout thrashing. + this.highlightEl.style.transform = `translate(${offset}px)`; + this.stickyHeaderEl.classList.toggle('lh-sticky-header--visible', showStickyHeader); + } +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = ReportUIFeatures; +} else { + self.ReportUIFeatures = ReportUIFeatures; +} +; +/** + * @license + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS-IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict'; + /* globals self, Util */ /** @typedef {import('./dom.js')} DOM */ @@ -2105,22 +2850,20 @@ class CategoryRenderer { /** * @param {LH.ReportResult.AuditRef} audit - * @param {number} index * @return {Element} */ - renderAudit(audit, index) { + renderAudit(audit) { const tmpl = this.dom.cloneTemplate('#tmpl-lh-audit', this.templateContext); - return this.populateAuditValues(audit, index, tmpl); + return this.populateAuditValues(audit, tmpl); } /** * Populate an DOM tree with audit details. Used by renderAudit and renderOpportunity * @param {LH.ReportResult.AuditRef} audit - * @param {number} index * @param {DocumentFragment} tmpl * @return {Element} */ - populateAuditValues(audit, index, tmpl) { + populateAuditValues(audit, tmpl) { const auditEl = this.dom.find('.lh-audit', tmpl); auditEl.id = audit.result.id; const scoreDisplayMode = audit.result.scoreDisplayMode; @@ -2134,6 +2877,24 @@ class CategoryRenderer { this.dom.find('.lh-audit__description', auditEl) .appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.description)); + if (audit.stackPacks) { + audit.stackPacks.forEach(pack => { + const packElm = this.dom.createElement('div'); + packElm.classList.add('lh-audit__stackpack'); + + const packElmImg = this.dom.createElement('img'); + packElmImg.classList.add('lh-audit__stackpack__img'); + packElmImg.src = pack.iconDataURL; + packElmImg.alt = pack.title; + packElm.appendChild(packElmImg); + + packElm.appendChild(this.dom.convertMarkdownLinkSnippets(pack.description)); + + this.dom.find('.lh-audit__stackpacks', auditEl) + .appendChild(packElm); + }); + } + const header = /** @type {HTMLDetailsElement} */ (this.dom.find('details', auditEl)); if (audit.result.details) { const elem = this.detailsRenderer.render(audit.result.details); @@ -2142,7 +2903,6 @@ class CategoryRenderer { header.appendChild(elem); } } - this.dom.find('.lh-audit__index', auditEl).textContent = `${index + 1}`; // Add chevron SVG to the end of the summary this.dom.find('.lh-chevron-container', auditEl).appendChild(this._createChevron()); @@ -2164,10 +2924,10 @@ class CategoryRenderer { // Add list of warnings or singular warning const warningsEl = this.dom.createChildOf(titleEl, 'div', 'lh-warnings'); + this.dom.createChildOf(warningsEl, 'span').textContent = Util.UIStrings.warningHeader; if (warnings.length === 1) { - warningsEl.textContent = `${Util.UIStrings.warningHeader} ${warnings.join('')}`; + warningsEl.appendChild(this.dom.document().createTextNode(warnings.join(''))); } else { - warningsEl.textContent = Util.UIStrings.warningHeader; const warningsUl = this.dom.createChildOf(warningsEl, 'ul'); for (const warning of warnings) { const item = this.dom.createChildOf(warningsUl, 'li'); @@ -2194,7 +2954,10 @@ class CategoryRenderer { */ _setRatingClass(element, score, scoreDisplayMode) { const rating = Util.calculateRating(score, scoreDisplayMode); - element.classList.add(`lh-audit--${rating}`, `lh-audit--${scoreDisplayMode.toLowerCase()}`); + element.classList.add(`lh-audit--${scoreDisplayMode.toLowerCase()}`); + if (scoreDisplayMode !== 'informative') { + element.classList.add(`lh-audit--${rating}`); + } return element; } @@ -2210,8 +2973,6 @@ class CategoryRenderer { const gaugeEl = this.renderScoreGauge(category, groupDefinitions); gaugeContainerEl.appendChild(gaugeEl); - this.dom.find('.lh-category-header__title', tmpl).appendChild( - this.dom.convertMarkdownCodeSnippets(category.title)); if (category.description) { const descEl = this.dom.convertMarkdownLinkSnippets(category.description); this.dom.find('.lh-category-header__description', tmpl).appendChild(descEl); @@ -2228,16 +2989,17 @@ class CategoryRenderer { */ renderAuditGroup(group) { const groupEl = this.dom.createElement('div', 'lh-audit-group'); - const summaryEl = this.dom.createChildOf(groupEl, 'div'); - const summaryInnerEl = this.dom.createChildOf(summaryEl, 'div', 'lh-audit-group__summary'); - const headerEl = this.dom.createChildOf(summaryInnerEl, 'div', 'lh-audit-group__header'); + const auditGroupHeader = this.dom.createElement('div', 'lh-audit-group__header'); + + this.dom.createChildOf(auditGroupHeader, 'span', 'lh-audit-group__title') + .textContent = group.title; if (group.description) { - const auditGroupDescription = this.dom.createElement('div', 'lh-audit-group__description'); - auditGroupDescription.appendChild(this.dom.convertMarkdownLinkSnippets(group.description)); - groupEl.appendChild(auditGroupDescription); + const descriptionEl = this.dom.convertMarkdownLinkSnippets(group.description); + descriptionEl.classList.add('lh-audit-group__description'); + auditGroupHeader.appendChild(descriptionEl); } - headerEl.textContent = group.title; + groupEl.appendChild(auditGroupHeader); return groupEl; } @@ -2267,14 +3029,12 @@ class CategoryRenderer { /** @type {Array} */ const auditElements = []; - // Continuous numbering across all groups. - let index = 0; for (const [groupId, groupAuditRefs] of grouped) { if (groupId === notAGroup) { // Push not-grouped audits individually. for (const auditRef of groupAuditRefs) { - auditElements.push(this.renderAudit(auditRef, index++)); + auditElements.push(this.renderAudit(auditRef)); } continue; } @@ -2283,7 +3043,7 @@ class CategoryRenderer { const groupDef = groupDefinitions[groupId]; const auditGroupElem = this.renderAuditGroup(groupDef); for (const auditRef of groupAuditRefs) { - auditGroupElem.appendChild(this.renderAudit(auditRef, index++)); + auditGroupElem.appendChild(this.renderAudit(auditRef)); } auditGroupElem.classList.add(`lh-audit-group--${groupId}`); auditElements.push(auditGroupElem); @@ -2327,17 +3087,15 @@ class CategoryRenderer { const headerEl = this.dom.find('.lh-audit-group__header', clumpElement); const title = this._clumpTitles[clumpId]; - headerEl.textContent = title; + this.dom.find('.lh-audit-group__title', headerEl).textContent = title; if (description) { - const markdownDescriptionEl = this.dom.convertMarkdownLinkSnippets(description); - const auditGroupDescription = this.dom.createElement('div', 'lh-audit-group__description'); - auditGroupDescription.appendChild(markdownDescriptionEl); - clumpElement.appendChild(auditGroupDescription); + const descriptionEl = this.dom.convertMarkdownLinkSnippets(description); + descriptionEl.classList.add('lh-audit-group__description'); + headerEl.appendChild(descriptionEl); } const itemCountEl = this.dom.find('.lh-audit-group__itemcount', clumpElement); - // TODO(i18n): support multiple locales here - itemCountEl.textContent = `${auditRefs.length} audits`; + itemCountEl.textContent = `(${auditRefs.length})`; // Add all audit results to the clump. const auditElements = auditRefs.map(this.renderAudit.bind(this)); @@ -2366,16 +3124,20 @@ class CategoryRenderer { wrapper.href = `#${category.id}`; wrapper.classList.add(`lh-gauge__wrapper--${Util.calculateRating(category.score)}`); + if (Util.isPluginCategory(category.id)) { + wrapper.classList.add('lh-gauge__wrapper--plugin'); + } + // Cast `null` to 0 const numericScore = Number(category.score); const gauge = this.dom.find('.lh-gauge', tmpl); - // 329 is ~= 2 * Math.PI * gauge radius (53) + // 352 is ~= 2 * Math.PI * gauge radius (56) // https://codepen.io/xgad/post/svg-radial-progress-meters - // score of 50: `stroke-dasharray: 164.5 329`; + // score of 50: `stroke-dasharray: 176 352`; /** @type {?SVGCircleElement} */ const gaugeArc = gauge.querySelector('.lh-gauge-arc'); if (gaugeArc) { - gaugeArc.style.strokeDasharray = `${numericScore * 329} 329`; + gaugeArc.style.strokeDasharray = `${numericScore * 352} 352`; } const scoreOutOf100 = Math.round(numericScore * 100); @@ -2425,19 +3187,19 @@ class CategoryRenderer { * manual, passed, or notApplicable. The result ends up something like: * * failed clump - * \\u251c\\u2500\\u2500 audit 1 (w/o group) - * \\u251c\\u2500\\u2500 audit 2 (w/o group) - * \\u251c\\u2500\\u2500 audit group - * | \\u251c\\u2500\\u2500 audit 3 - * | \\u2514\\u2500\\u2500 audit 4 - * \\u2514\\u2500\\u2500 audit group - * \\u251c\\u2500\\u2500 audit 5 - * \\u2514\\u2500\\u2500 audit 6 + * ├── audit 1 (w/o group) + * ├── audit 2 (w/o group) + * ├── audit group + * | ├── audit 3 + * | └── audit 4 + * └── audit group + * ├── audit 5 + * └── audit 6 * other clump (e.g. 'manual') - * \\u251c\\u2500\\u2500 audit 1 - * \\u251c\\u2500\\u2500 audit 2 - * \\u251c\\u2500\\u2500 \\u2026 - * \\u22ee + * ├── audit 1 + * ├── audit 2 + * ├── … + * ⋮ * @param {LH.ReportResult.Category} category * @param {Object} [groupDefinitions] * @return {Element} @@ -2555,13 +3317,12 @@ class PerformanceCategoryRenderer extends CategoryRenderer { /** * @param {LH.ReportResult.AuditRef} audit - * @param {number} index * @param {number} scale * @return {Element} */ - _renderOpportunity(audit, index, scale) { + _renderOpportunity(audit, scale) { const oppTmpl = this.dom.cloneTemplate('#tmpl-lh-opportunity', this.templateContext); - const element = this.populateAuditValues(audit, index, oppTmpl); + const element = this.populateAuditValues(audit, oppTmpl); element.id = audit.result.id; if (!audit.result.details || audit.result.scoreDisplayMode === 'error') { @@ -2625,10 +3386,15 @@ class PerformanceCategoryRenderer extends CategoryRenderer { element.appendChild(this.renderCategoryHeader(category, groups)); } - // Metrics + // Metrics. const metricAudits = category.auditRefs.filter(audit => audit.group === 'metrics'); const metricAuditsEl = this.renderAuditGroup(groups.metrics); + // Metric descriptions toggle. + const toggleTmpl = this.dom.cloneTemplate('#tmpl-lh-metrics-toggle', this.templateContext); + const toggleEl = this.dom.find('.lh-metrics-toggle', toggleTmpl); + metricAuditsEl.prepend(...toggleEl.childNodes); + const keyMetrics = metricAudits.filter(a => a.weight >= 3); const otherMetrics = metricAudits.filter(a => a.weight < 3); @@ -2645,8 +3411,7 @@ class PerformanceCategoryRenderer extends CategoryRenderer { // 'Values are estimated and may vary' is used as the category description for PSI if (environment !== 'PSI') { - const estValuesEl = this.dom.createChildOf(metricsColumn2El, 'div', - 'lh-metrics__disclaimer lh-metrics__disclaimer'); + const estValuesEl = this.dom.createChildOf(metricAuditsEl, 'div', 'lh-metrics__disclaimer'); estValuesEl.textContent = Util.UIStrings.varianceDisclaimer; } @@ -2663,6 +3428,20 @@ class PerformanceCategoryRenderer extends CategoryRenderer { filmstripEl && timelineEl.appendChild(filmstripEl); } + // Budgets + const budgetAudit = category.auditRefs.find(audit => audit.id === 'performance-budget'); + if (budgetAudit && budgetAudit.result.details) { + const table = this.detailsRenderer.render(budgetAudit.result.details); + if (table) { + table.id = budgetAudit.id; + table.classList.add('lh-audit'); + const budgetsGroupEl = this.renderAuditGroup(groups.budgets); + budgetsGroupEl.appendChild(table); + budgetsGroupEl.classList.add('lh-audit-group--budgets'); + element.appendChild(budgetsGroupEl); + } + } + // Opportunities const opportunityAudits = category.auditRefs .filter(audit => audit.group === 'load-opportunities' && !Util.showAsPassed(audit.result)) @@ -2684,8 +3463,7 @@ class PerformanceCategoryRenderer extends CategoryRenderer { const headerEl = this.dom.find('.lh-load-opportunity__header', tmpl); groupEl.appendChild(headerEl); - opportunityAudits.forEach((item, i) => - groupEl.appendChild(this._renderOpportunity(item, i, scale))); + opportunityAudits.forEach(item => groupEl.appendChild(this._renderOpportunity(item, scale))); groupEl.classList.add('lh-audit-group--load-opportunities'); element.appendChild(groupEl); } @@ -2701,7 +3479,7 @@ class PerformanceCategoryRenderer extends CategoryRenderer { if (diagnosticAudits.length) { const groupEl = this.renderAuditGroup(groups['diagnostics']); - diagnosticAudits.forEach((item, i) => groupEl.appendChild(this.renderAudit(item, i))); + diagnosticAudits.forEach(item => groupEl.appendChild(this.renderAudit(item))); groupEl.classList.add('lh-audit-group--diagnostics'); element.appendChild(groupEl); } @@ -2961,36 +3739,24 @@ class ReportRenderer { * @param {LH.ReportResult} report * @return {DocumentFragment} */ - _renderReportHeader(report) { - const el = this._dom.cloneTemplate('#tmpl-lh-heading', this._templateContext); - const domFragment = this._dom.cloneTemplate('#tmpl-lh-scores-wrapper', this._templateContext); - const placeholder = this._dom.find('.lh-scores-wrapper-placeholder', el); - /** @type {HTMLDivElement} */ (placeholder.parentNode).replaceChild(domFragment, placeholder); - - this._dom.find('.lh-config__timestamp', el).textContent = - Util.formatDateTime(report.fetchTime); - this._dom.find('.lh-product-info__version', el).textContent = report.lighthouseVersion; - const metadataUrl = /** @type {HTMLAnchorElement} */ (this._dom.find('.lh-metadata__url', el)); - const toolbarUrl = /** @type {HTMLAnchorElement}*/ (this._dom.find('.lh-toolbar__url', el)); + _renderReportTopbar(report) { + const el = this._dom.cloneTemplate('#tmpl-lh-topbar', this._templateContext); + const metadataUrl = /** @type {HTMLAnchorElement} */ (this._dom.find('.lh-topbar__url', el)); metadataUrl.href = metadataUrl.textContent = report.finalUrl; - toolbarUrl.href = toolbarUrl.textContent = report.finalUrl; - - const emulationDescriptions = Util.getEmulationDescriptions(report.configSettings || {}); - this._dom.find('.lh-config__emulation', el).textContent = emulationDescriptions.summary; return el; } /** - * @return {Element} + * @return {DocumentFragment} */ - _renderReportShortHeader() { - const shortHeaderContainer = this._dom.createElement('div', 'lh-header-container'); - const wrapper = this._dom.cloneTemplate('#tmpl-lh-scores-wrapper', this._templateContext); - shortHeaderContainer.appendChild(wrapper); - return shortHeaderContainer; + _renderReportHeader() { + const el = this._dom.cloneTemplate('#tmpl-lh-heading', this._templateContext); + const domFragment = this._dom.cloneTemplate('#tmpl-lh-scores-wrapper', this._templateContext); + const placeholder = this._dom.find('.lh-scores-wrapper-placeholder', el); + /** @type {HTMLDivElement} */ (placeholder.parentNode).replaceChild(domFragment, placeholder); + return el; } - /** * @param {LH.ReportResult} report * @return {DocumentFragment} @@ -3014,7 +3780,7 @@ class ReportRenderer { if (!runtime.description) return; const item = this._dom.cloneTemplate('#tmpl-lh-env__items', env); - this._dom.find('.lh-env__name', item).textContent = `${runtime.name}:`; + this._dom.find('.lh-env__name', item).textContent = runtime.name; this._dom.find('.lh-env__description', item).textContent = runtime.description; env.appendChild(item); }); @@ -3048,33 +3814,42 @@ class ReportRenderer { /** * @param {LH.ReportResult} report - * @return {DocumentFragment} + * @param {CategoryRenderer} categoryRenderer + * @param {Record} specificCategoryRenderers + * @return {DocumentFragment[]} */ - _renderReport(report) { - let header; - const headerContainer = this._dom.createElement('div'); - if (this._dom.isDevTools()) { - headerContainer.classList.add('lh-header-plain'); - header = this._renderReportShortHeader(); - } else { - headerContainer.classList.add('lh-header-sticky'); - header = this._renderReportHeader(report); - } - headerContainer.appendChild(header); - - const container = this._dom.createElement('div', 'lh-container'); - const reportSection = container.appendChild(this._dom.createElement('div', 'lh-report')); + _renderScoreGauges(report, categoryRenderer, specificCategoryRenderers) { + // Group gauges in this order: default, pwa, plugins. + const defaultGauges = []; + const customGauges = []; // PWA. + const pluginGauges = []; - reportSection.appendChild(this._renderReportWarnings(report)); - - let scoreHeader; - const isSoloCategory = report.reportCategories.length === 1; - if (!isSoloCategory) { - scoreHeader = this._dom.createElement('div', 'lh-scores-header'); - } else { - headerContainer.classList.add('lh-header--solo-category'); + for (const category of Object.values(report.categories)) { + const renderer = specificCategoryRenderers[category.id] || categoryRenderer; + const categoryGauge = renderer.renderScoreGauge(category, report.categoryGroups || {}); + + if (Util.isPluginCategory(category.id)) { + pluginGauges.push(categoryGauge); + } else if (renderer.renderScoreGauge === categoryRenderer.renderScoreGauge) { + // The renderer for default categories is just the default CategoryRenderer. + // If the functions are equal, then renderer is an instance of CategoryRenderer. + // For example, the PWA category uses PwaCategoryRenderer, which overrides + // CategoryRenderer.renderScoreGauge, so it would fail this check and be placed + // in the customGauges bucket. + defaultGauges.push(categoryGauge); + } else { + customGauges.push(categoryGauge); + } } + return [...defaultGauges, ...customGauges, ...pluginGauges]; + } + + /** + * @param {LH.ReportResult} report + * @return {DocumentFragment} + */ + _renderReport(report) { const detailsRenderer = new DetailsRenderer(this._dom); const categoryRenderer = new CategoryRenderer(this._dom, detailsRenderer); categoryRenderer.setTemplateContext(this._templateContext); @@ -3088,51 +3863,52 @@ class ReportRenderer { renderer.setTemplateContext(this._templateContext); }); - const categories = reportSection.appendChild(this._dom.createElement('div', 'lh-categories')); + const headerContainer = this._dom.createElement('div'); + headerContainer.appendChild(this._renderReportHeader()); - for (const category of report.reportCategories) { - const renderer = specificCategoryRenderers[category.id] || categoryRenderer; - categories.appendChild(renderer.render(category, report.categoryGroups)); - } + const container = this._dom.createElement('div', 'lh-container'); + const reportSection = this._dom.createElement('div', 'lh-report'); + reportSection.appendChild(this._renderReportWarnings(report)); - // Fireworks - const scoresAll100 = report.reportCategories.every(cat => cat.score === 1); - if (!this._dom.isDevTools() && scoresAll100) { - headerContainer.classList.add('score100'); - this._dom.find('.lh-header', headerContainer).addEventListener('click', _ => { - headerContainer.classList.toggle('fireworks-paused'); - }); + let scoreHeader; + const isSoloCategory = Object.keys(report.categories).length === 1; + if (!isSoloCategory) { + scoreHeader = this._dom.createElement('div', 'lh-scores-header'); + } else { + headerContainer.classList.add('lh-header--solo-category'); } if (scoreHeader) { - const defaultGauges = []; - const customGauges = []; - for (const category of report.reportCategories) { - const renderer = specificCategoryRenderers[category.id] || categoryRenderer; - const categoryGauge = renderer.renderScoreGauge(category, report.categoryGroups || {}); - - // Group gauges that aren't default at the end of the header - if (renderer.renderScoreGauge === categoryRenderer.renderScoreGauge) { - defaultGauges.push(categoryGauge); - } else { - customGauges.push(categoryGauge); - } - } - scoreHeader.append(...defaultGauges, ...customGauges); - const scoreScale = this._dom.cloneTemplate('#tmpl-lh-scorescale', this._templateContext); - this._dom.find('.lh-scorescale-label', scoreScale).textContent = - Util.UIStrings.scorescaleLabel; const scoresContainer = this._dom.find('.lh-scores-container', headerContainer); + scoreHeader.append( + ...this._renderScoreGauges(report, categoryRenderer, specificCategoryRenderers)); scoresContainer.appendChild(scoreHeader); scoresContainer.appendChild(scoreScale); + + const stickyHeader = this._dom.createElement('div', 'lh-sticky-header'); + stickyHeader.append( + ...this._renderScoreGauges(report, categoryRenderer, specificCategoryRenderers)); + container.appendChild(stickyHeader); } - reportSection.appendChild(this._renderReportFooter(report)); + const categories = reportSection.appendChild(this._dom.createElement('div', 'lh-categories')); + for (const category of Object.values(report.categories)) { + const renderer = specificCategoryRenderers[category.id] || categoryRenderer; + // .lh-category-wrapper is full-width and provides horizontal rules between categories. + // .lh-category within has the max-width: var(--report-width); + const wrapper = renderer.dom.createChildOf(categories, 'div', 'lh-category-wrapper'); + wrapper.appendChild(renderer.render(category, report.categoryGroups)); + } const reportFragment = this._dom.createFragment(); - reportFragment.appendChild(headerContainer); + const topbarDocumentFragment = this._renderReportTopbar(report); + + reportFragment.appendChild(topbarDocumentFragment); reportFragment.appendChild(container); + container.appendChild(headerContainer); + container.appendChild(reportSection); + reportSection.appendChild(this._renderReportFooter(report)); return reportFragment; } diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/templates.html b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/templates.html index c63bc666fd3..ee4b388c69a 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/templates.html +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/templates.html @@ -26,10 +26,9 @@ limitations under the License. @@ -47,7 +46,6 @@ limitations under the License. @@ -58,28 +56,53 @@ limitations under the License.
-
-
+
+ + + + +
+ + + @@ -87,10 +110,10 @@ limitations under the License. @@ -103,7 +126,7 @@ limitations under the License.
- +
@@ -117,11 +140,11 @@ limitations under the License.
+
- - - - - - .lh-product-info, .lh-toolbar__metadata { - align-items: center; - white-space: nowrap; - color: #5F6369; + + + + + @@ -530,35 +494,50 @@ limitations under the License. - + diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js index 08e23b8d065..445954ab46d 100644 --- a/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js +++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js @@ -1,4 +1,4 @@ -// lighthouse, browserified. 4.3.1 (5c48bb8eaff9a9a3709d6253d3cacdccf11a139a) +// lighthouse, browserified. 5.1.0 (c10ea6e3bd0399174b3110a67c21be293e11baa7) require=function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u="function"==typeof require&&require,i=0;iel.rel==='apple-touch-icon'||el.rel==='apple-touch-icon-precomposed'). +filter(el=>!!el.href); + + +const passed=appleTouchIcons.length!==0; + +const warnings=[]; +if(appleTouchIcons.filter(el=>el.rel==='apple-touch-icon-precomposed').length!==0&& +appleTouchIcons.filter(el=>el.rel==='apple-touch-icon').length===0){ +warnings.push(str_(UIStrings.precomposedWarning)); +} + +return{ +score:passed?1:0, +warnings}; + +}} + + +module.exports=AppleTouchIcon; +module.exports.UIStrings=UIStrings; + +}).call(this,"/lighthouse-core/audits/apple-touch-icon.js"); +},{"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/bootup-time":[function(require,module,exports){ (function(__filename){ @@ -2084,9 +2159,9 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); -const NetworkRequest=require('../lib/network-request'); -const{taskGroups}=require('../lib/task-groups'); +const Audit=require('./audit.js'); +const NetworkRequest=require('../lib/network-request.js'); +const{taskGroups}=require('../lib/task-groups.js'); const i18n=require('../lib/i18n/i18n.js'); const NetworkRecords=require('../computed/network-records.js'); const MainThreadTasks=require('../computed/main-thread-tasks.js'); @@ -2124,7 +2199,7 @@ title:str_(UIStrings.title), failureTitle:str_(UIStrings.failureTitle), description:str_(UIStrings.description), scoreDisplayMode:Audit.SCORING_MODES.NUMERIC, -requiredArtifacts:['traces']}; +requiredArtifacts:['traces','devtoolsLogs']}; } @@ -2258,7 +2333,7 @@ context.options.scoreMedian); return{ score, -rawValue:totalBootupTime, +numericValue:totalBootupTime, displayValue:totalBootupTime>0? str_(i18n.UIStrings.seconds,{timeInMs:totalBootupTime}):'', details}; @@ -2270,7 +2345,7 @@ module.exports=BootupTime; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/bootup-time.js"); -},{"../computed/main-thread-tasks.js":12,"../computed/network-records.js":31,"../lib/i18n/i18n.js":63,"../lib/network-request":71,"../lib/task-groups":77,"./audit":3}],"../audits/byte-efficiency/efficient-animated-content":[function(require,module,exports){ +},{"../computed/main-thread-tasks.js":12,"../computed/network-records.js":31,"../lib/i18n/i18n.js":66,"../lib/network-request.js":74,"../lib/task-groups.js":82,"./audit.js":3}],"../audits/byte-efficiency/efficient-animated-content":[function(require,module,exports){ (function(__filename){ @@ -2282,8 +2357,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const NetworkRequest=require('../../lib/network-request'); -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); +const NetworkRequest=require('../../lib/network-request.js'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -2366,7 +2441,7 @@ module.exports=EfficientAnimatedContent; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/network-request":71,"./byte-efficiency-audit":4}],"../audits/byte-efficiency/offscreen-images":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/network-request.js":74,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/offscreen-images":[function(require,module,exports){ (function(__filename){ @@ -2379,9 +2454,9 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); -const Sentry=require('../../lib/sentry'); -const URL=require('../../lib/url-shim'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); +const Sentry=require('../../lib/sentry.js'); +const URL=require('../../lib/url-shim.js'); const i18n=require('../../lib/i18n/i18n.js'); const Interactive=require('../../computed/metrics/interactive.js'); const TraceOfTab=require('../../computed/trace-of-tab.js'); @@ -2613,7 +2688,7 @@ module.exports=OffscreenImages; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/offscreen-images.js"); -},{"../../computed/metrics/interactive.js":18,"../../computed/trace-of-tab.js":35,"../../lib/i18n/i18n.js":63,"../../lib/sentry":74,"../../lib/url-shim":"url","./byte-efficiency-audit":4}],"../audits/byte-efficiency/render-blocking-resources":[function(require,module,exports){ +},{"../../computed/metrics/interactive.js":18,"../../computed/trace-of-tab.js":36,"../../lib/i18n/i18n.js":66,"../../lib/sentry.js":77,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/render-blocking-resources":[function(require,module,exports){ (function(__filename){ @@ -2626,12 +2701,12 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); -const BaseNode=require('../../lib/dependency-graph/base-node'); -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); -const UnusedCSS=require('./unused-css-rules'); -const NetworkRequest=require('../../lib/network-request'); +const BaseNode=require('../../lib/dependency-graph/base-node.js'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); +const UnusedCSS=require('./unused-css-rules.js'); +const NetworkRequest=require('../../lib/network-request.js'); const TraceOfTab=require('../../computed/trace-of-tab.js'); const LoadSimulator=require('../../computed/load-simulator.js'); const FirstContentfulPaint=require('../../computed/metrics/first-contentful-paint.js'); @@ -2689,8 +2764,7 @@ scoreDisplayMode:Audit.SCORING_MODES.NUMERIC, description:str_(UIStrings.description), - -requiredArtifacts:['URL','TagsBlockingFirstPaint','traces']}; +requiredArtifacts:['URL','TagsBlockingFirstPaint','traces','devtoolsLogs','CSSUsage']}; } @@ -2841,7 +2915,7 @@ const details=Audit.makeOpportunityDetails(headings,results,wastedMs); return{ displayValue, score:ByteEfficiencyAudit.scoreForWastedMs(wastedMs), -rawValue:wastedMs, +numericValue:wastedMs, details}; }} @@ -2851,7 +2925,7 @@ module.exports=RenderBlockingResources; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js"); -},{"../../computed/load-simulator.js":10,"../../computed/metrics/first-contentful-paint.js":15,"../../computed/trace-of-tab.js":35,"../../lib/dependency-graph/base-node":52,"../../lib/i18n/i18n.js":63,"../../lib/network-request":71,"../audit":3,"./byte-efficiency-audit":4,"./unused-css-rules":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/total-byte-weight":[function(require,module,exports){ +},{"../../computed/load-simulator.js":10,"../../computed/metrics/first-contentful-paint.js":15,"../../computed/trace-of-tab.js":36,"../../lib/dependency-graph/base-node.js":55,"../../lib/i18n/i18n.js":66,"../../lib/network-request.js":74,"../audit.js":3,"./byte-efficiency-audit.js":4,"./unused-css-rules.js":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/total-byte-weight":[function(require,module,exports){ (function(__filename){ @@ -2860,7 +2934,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const NetworkRecords=require('../../computed/network-records.js'); @@ -2954,7 +3028,7 @@ const tableDetails=ByteEfficiencyAudit.makeTableDetails(headings,results); return{ score, -rawValue:totalBytes, +numericValue:totalBytes, displayValue:str_(UIStrings.displayValue,{totalBytes}), extendedInfo:{ value:{ @@ -2971,7 +3045,7 @@ module.exports=TotalByteWeight; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/total-byte-weight.js"); -},{"../../computed/network-records.js":31,"../../lib/i18n/i18n.js":63,"./byte-efficiency-audit":4}],"../audits/byte-efficiency/unminified-css":[function(require,module,exports){ +},{"../../computed/network-records.js":31,"../../lib/i18n/i18n.js":66,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unminified-css":[function(require,module,exports){ (function(__filename){ @@ -2980,10 +3054,10 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); -const UnusedCSSRules=require('./unused-css-rules'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); +const UnusedCSSRules=require('./unused-css-rules.js'); const i18n=require('../../lib/i18n/i18n.js'); -const computeTokenLength=require('../../lib/minification-estimator').computeCSSTokenLength; +const computeTokenLength=require('../../lib/minification-estimator.js').computeCSSTokenLength; const UIStrings={ @@ -3011,7 +3085,7 @@ id:'unminified-css', title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC, -requiredArtifacts:['CSSUsage','devtoolsLogs','traces']}; +requiredArtifacts:['CSSUsage','devtoolsLogs','traces','URL']}; } @@ -3092,7 +3166,7 @@ module.exports=UnminifiedCSS; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/unminified-css.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/minification-estimator":69,"./byte-efficiency-audit":4,"./unused-css-rules":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/unminified-javascript":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/minification-estimator.js":72,"./byte-efficiency-audit.js":4,"./unused-css-rules.js":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/unminified-javascript":[function(require,module,exports){ (function(__filename){ @@ -3101,9 +3175,9 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); const i18n=require('../../lib/i18n/i18n.js'); -const computeTokenLength=require('../../lib/minification-estimator').computeJSTokenLength; +const computeTokenLength=require('../../lib/minification-estimator.js').computeJSTokenLength; const UIStrings={ @@ -3214,7 +3288,7 @@ module.exports=UnminifiedJavaScript; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/unminified-javascript.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/minification-estimator":69,"./byte-efficiency-audit":4}],"../audits/byte-efficiency/unused-css-rules":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/minification-estimator.js":72,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unused-css-rules":[function(require,module,exports){ (function(__filename){ @@ -3223,7 +3297,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -3409,7 +3483,7 @@ module.exports=UnusedCSSRules; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/unused-css-rules.js"); -},{"../../lib/i18n/i18n.js":63,"./byte-efficiency-audit":4}],"../audits/byte-efficiency/unused-javascript":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unused-javascript":[function(require,module,exports){ (function(__filename){ @@ -3418,7 +3492,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -3547,7 +3621,7 @@ module.exports=UnusedJavaScript; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/unused-javascript.js"); -},{"../../lib/i18n/i18n.js":63,"./byte-efficiency-audit":4}],"../audits/byte-efficiency/uses-long-cache-ttl":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-long-cache-ttl":[function(require,module,exports){ (function(__filename){ @@ -3558,10 +3632,10 @@ module.exports.UIStrings=UIStrings; const assert=require('assert'); const parseCacheControl=require('parse-cache-control'); -const Audit=require('../audit'); -const NetworkRequest=require('../../lib/network-request'); -const URL=require('../../lib/url-shim'); -const linearInterpolation=require('../../lib/statistics').linearInterpolation; +const Audit=require('../audit.js'); +const NetworkRequest=require('../../lib/network-request.js'); +const URL=require('../../lib/url-shim.js'); +const linearInterpolation=require('../../lib/statistics.js').linearInterpolation; const i18n=require('../../lib/i18n/i18n.js'); const NetworkRecords=require('../../computed/network-records.js'); @@ -3703,11 +3777,12 @@ NetworkRequest.TYPES.Script, NetworkRequest.TYPES.Stylesheet]); -const resourceUrl=record.url; + +if(URL.NON_NETWORK_PROTOCOLS.includes(record.protocol))return false; + return( CACHEABLE_STATUS_CODES.has(record.statusCode)&& -STATIC_RESOURCE_TYPES.has(record.resourceType||'Other')&& -!resourceUrl.includes('data:')); +STATIC_RESOURCE_TYPES.has(record.resourceType||'Other')); } @@ -3790,17 +3865,17 @@ if(url.includes('?'))queryStringCount++; -let diagnostic; +let debugData; if(cacheControl){ -diagnostic={ -type:'diagnostic', +debugData={ +type:'debugdata', ...cacheControl}; } results.push({ url, -diagnostic, +debugData, cacheLifetimeMs:cacheLifetimeInSeconds*1000, cacheHitProbability, totalBytes, @@ -3835,7 +3910,7 @@ const details=Audit.makeTableDetails(headings,results,summary); return{ score, -rawValue:totalWastedBytes, +numericValue:totalWastedBytes, displayValue:str_(UIStrings.displayValue,{itemCount:results.length}), extendedInfo:{ value:{ @@ -3853,7 +3928,7 @@ module.exports=CacheHeaders; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js"); -},{"../../computed/network-records.js":31,"../../lib/i18n/i18n.js":63,"../../lib/network-request":71,"../../lib/statistics":75,"../../lib/url-shim":"url","../audit":3,"assert":84,"parse-cache-control":134}],"../audits/byte-efficiency/uses-optimized-images":[function(require,module,exports){ +},{"../../computed/network-records.js":31,"../../lib/i18n/i18n.js":66,"../../lib/network-request.js":74,"../../lib/statistics.js":80,"../../lib/url-shim.js":"url","../audit.js":3,"assert":89,"parse-cache-control":139}],"../audits/byte-efficiency/uses-optimized-images":[function(require,module,exports){ (function(__filename){ @@ -3866,8 +3941,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); -const URL=require('../../lib/url-shim'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); +const URL=require('../../lib/url-shim.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -3892,7 +3967,7 @@ id:'uses-optimized-images', title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC, -requiredArtifacts:['OptimizedImages','ImageElements','devtoolsLogs','traces']}; +requiredArtifacts:['OptimizedImages','ImageElements','devtoolsLogs','traces','URL']}; } @@ -3992,7 +4067,7 @@ module.exports=UsesOptimizedImages; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/uses-optimized-images.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","./byte-efficiency-audit":4}],"../audits/byte-efficiency/uses-responsive-images":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-responsive-images":[function(require,module,exports){ (function(__filename){ @@ -4009,9 +4084,9 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); -const Sentry=require('../../lib/sentry'); -const URL=require('../../lib/url-shim'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); +const Sentry=require('../../lib/sentry.js'); +const URL=require('../../lib/url-shim.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -4090,19 +4165,22 @@ const DPR=artifacts.ViewportDimensions.devicePixelRatio; const warnings=[]; const resultsMap=new Map(); -images.forEach(image=>{ +for(const image of images){ -if(!image.resourceSize||image.mimeType==='image/svg+xml'){ -return; + + + +if(!image.resourceSize||image.mimeType==='image/svg+xml'||image.isCss){ +continue; } const processed=UsesResponsiveImages.computeWaste(image,DPR); -if(!processed)return; +if(!processed)continue; if(processed instanceof Error){ warnings.push(processed.message); Sentry.captureException(processed,{tags:{audit:this.meta.id},level:'warning'}); -return; +continue; } @@ -4110,7 +4188,7 @@ const existing=resultsMap.get(processed.url); if(!existing||existing.wastedBytes>processed.wastedBytes){ resultsMap.set(processed.url,processed); } -}); +} const items=Array.from(resultsMap.values()). filter(item=>item.wastedBytes>IGNORE_THRESHOLD_IN_BYTES); @@ -4135,7 +4213,7 @@ module.exports=UsesResponsiveImages; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/sentry":74,"../../lib/url-shim":"url","./byte-efficiency-audit":4}],"../audits/byte-efficiency/uses-text-compression":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/sentry.js":77,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-text-compression":[function(require,module,exports){ (function(__filename){ @@ -4148,8 +4226,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); -const URL=require('../../lib/url-shim'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); +const URL=require('../../lib/url-shim.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -4239,7 +4317,7 @@ module.exports=ResponsesAreCompressed; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/uses-text-compression.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","./byte-efficiency-audit":4}],"../audits/byte-efficiency/uses-webp-images":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-webp-images":[function(require,module,exports){ (function(__filename){ @@ -4251,8 +4329,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ByteEfficiencyAudit=require('./byte-efficiency-audit'); -const URL=require('../../lib/url-shim'); +const ByteEfficiencyAudit=require('./byte-efficiency-audit.js'); +const URL=require('../../lib/url-shim.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -4278,7 +4356,7 @@ id:'uses-webp-images', title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC, -requiredArtifacts:['OptimizedImages','devtoolsLogs','traces']}; +requiredArtifacts:['OptimizedImages','devtoolsLogs','traces','URL','ImageElements']}; } @@ -4377,7 +4455,7 @@ module.exports=UsesWebPImages; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/byte-efficiency/uses-webp-images.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","./byte-efficiency-audit":4}],"../audits/content-width":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/content-width":[function(require,module,exports){ @@ -4385,7 +4463,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); class ContentWidth extends Audit{ @@ -4415,12 +4493,12 @@ const widthsMatch=viewportWidth===windowWidth; if(IsMobile){ return{ -rawValue:widthsMatch, +score:Number(widthsMatch), explanation:this.createExplanation(widthsMatch,artifacts.ViewportDimensions)}; }else{ return{ -rawValue:true, +score:1, notApplicable:true}; } @@ -4443,7 +4521,7 @@ return'The viewport size is '+artifact.innerWidth+'px, '+ module.exports=ContentWidth; -},{"./audit":3}],"../audits/critical-request-chains":[function(require,module,exports){ +},{"./audit.js":3}],"../audits/critical-request-chains":[function(require,module,exports){ (function(__filename){ @@ -4452,7 +4530,7 @@ module.exports=ContentWidth; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); const i18n=require('../lib/i18n/i18n.js'); const ComputedChains=require('../computed/critical-request-chains.js'); @@ -4648,7 +4726,7 @@ walk(initialNavChildren,0); const longestChain=CriticalRequestChains._getLongestChain(flattenedChains); return{ -rawValue:chainCount===0, +score:Number(chainCount===0), notApplicable:chainCount===0, displayValue:chainCount?str_(UIStrings.displayValue,{itemCount:chainCount}):'', extendedInfo:{ @@ -4671,7 +4749,7 @@ module.exports=CriticalRequestChains; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/critical-request-chains.js"); -},{"../computed/critical-request-chains.js":9,"../lib/i18n/i18n.js":63,"./audit":3}],"../audits/deprecations":[function(require,module,exports){ +},{"../computed/critical-request-chains.js":9,"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/deprecations":[function(require,module,exports){ @@ -4685,8 +4763,8 @@ module.exports.UIStrings=UIStrings; -const Audit=require('./audit'); -const Util=require('../report/html/renderer/util'); +const Audit=require('./audit.js'); +const Util=require('../report/html/renderer/util.js'); class Deprecations extends Audit{ @@ -4699,7 +4777,7 @@ title:'Avoids deprecated APIs', failureTitle:'Uses deprecated APIs', description:'Deprecated APIs will eventually be removed from the browser. '+ '[Learn more](https://www.chromestatus.com/features#deprecated).', -requiredArtifacts:['ChromeConsoleMessages']}; +requiredArtifacts:['ConsoleMessages']}; } @@ -4708,7 +4786,7 @@ requiredArtifacts:['ChromeConsoleMessages']}; static audit(artifacts){ -const entries=artifacts.ChromeConsoleMessages; +const entries=artifacts.ConsoleMessages; const deprecations=entries.filter(log=>log.entry.source==='deprecation').map(log=>{ return{ @@ -4735,7 +4813,7 @@ displayValue=`${deprecations.length} warning found`; } return{ -rawValue:deprecations.length===0, +score:Number(deprecations.length===0), displayValue, extendedInfo:{ value:deprecations}, @@ -4747,7 +4825,7 @@ details}; module.exports=Deprecations; -},{"../report/html/renderer/util":80,"./audit":3}],"../audits/diagnostics":[function(require,module,exports){ +},{"../report/html/renderer/util.js":85,"./audit.js":3}],"../audits/diagnostics":[function(require,module,exports){ @@ -4816,9 +4894,8 @@ mainDocumentTransferSize}; return{ score:1, -rawValue:1, details:{ -type:'diagnostic', +type:'debugdata', items:[diagnostics]}}; @@ -4828,7 +4905,7 @@ items:[diagnostics]}}; module.exports=Diagnostics; -},{"../computed/main-thread-tasks.js":12,"../computed/network-analysis.js":30,"../computed/network-records.js":31,"../lib/dependency-graph/simulator/network-analyzer.js":57,"./audit.js":3}],"../audits/dobetterweb/appcache-manifest":[function(require,module,exports){ +},{"../computed/main-thread-tasks.js":12,"../computed/network-analysis.js":30,"../computed/network-records.js":31,"../lib/dependency-graph/simulator/network-analyzer.js":60,"./audit.js":3}],"../audits/dobetterweb/appcache-manifest":[function(require,module,exports){ @@ -4841,7 +4918,7 @@ module.exports=Diagnostics; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); class AppCacheManifestAttr extends Audit{ @@ -4867,7 +4944,7 @@ const usingAppcache=artifacts.AppCacheManifest!==null; const displayValue=usingAppcache?`Found "${artifacts.AppCacheManifest}"`:''; return{ -rawValue:!usingAppcache, +score:usingAppcache?0:1, displayValue}; }} @@ -4875,7 +4952,7 @@ displayValue}; module.exports=AppCacheManifestAttr; -},{"../audit":3}],"../audits/dobetterweb/doctype":[function(require,module,exports){ +},{"../audit.js":3}],"../audits/dobetterweb/doctype":[function(require,module,exports){ @@ -4883,7 +4960,7 @@ module.exports=AppCacheManifestAttr; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); class Doctype extends Audit{ @@ -4908,7 +4985,7 @@ requiredArtifacts:['Doctype']}; static audit(artifacts){ if(!artifacts.Doctype){ return{ -rawValue:false, +score:0, explanation:'Document must contain a doctype'}; } @@ -4920,14 +4997,14 @@ const doctypeSystemId=artifacts.Doctype.systemId; if(doctypePublicId!==''){ return{ -rawValue:false, +score:0, explanation:'Expected publicId to be an empty string'}; } if(doctypeSystemId!==''){ return{ -rawValue:false, +score:0, explanation:'Expected systemId to be an empty string'}; } @@ -4937,11 +5014,11 @@ explanation:'Expected systemId to be an empty string'}; if(doctypeName==='html'){ return{ -rawValue:true}; +score:1}; }else{ return{ -rawValue:false, +score:0, explanation:'Doctype name must be the lowercase string `html`'}; } @@ -4950,7 +5027,7 @@ explanation:'Doctype name must be the lowercase string `html`'}; module.exports=Doctype; -},{"../audit":3}],"../audits/dobetterweb/dom-size":[function(require,module,exports){ +},{"../audit.js":3}],"../audits/dobetterweb/dom-size":[function(require,module,exports){ (function(__filename){ @@ -4966,11 +5043,11 @@ module.exports=Doctype; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const Util=require('../../report/html/renderer/util.js'); const i18n=require('../../lib/i18n/i18n.js'); -const MAX_DOM_NODES=1500; +const MAX_DOM_ELEMENTS=1500; const MAX_DOM_TREE_WIDTH=60; const MAX_DOM_TREE_DEPTH=32; @@ -4981,7 +5058,7 @@ title:'Avoids an excessive DOM size', failureTitle:'Avoid an excessive DOM size', description:'Browser engineers recommend pages contain fewer than '+ -`~${MAX_DOM_NODES.toLocaleString()} DOM nodes. The sweet spot is a tree `+ +`~${MAX_DOM_ELEMENTS.toLocaleString()} DOM elements. The sweet spot is a tree `+ `depth < ${MAX_DOM_TREE_DEPTH} elements and fewer than ${MAX_DOM_TREE_WIDTH} `+ 'children/parent element. A large DOM can increase memory usage, cause longer '+ '[style calculations](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), '+ @@ -4994,11 +5071,11 @@ columnElement:'Element', columnValue:'Value', displayValue:`{itemCount, plural, - =1 {1 node} - other {# nodes} + =1 {1 element} + other {# elements} }`, -statisticDOMNodes:'Total DOM Nodes', +statisticDOMElements:'Total DOM Elements', statisticDOMDepth:'Maximum DOM Depth', @@ -5009,8 +5086,8 @@ const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings); class DOMSize extends Audit{ -static get MAX_DOM_NODES(){ -return MAX_DOM_NODES; +static get MAX_DOM_ELEMENTS(){ +return MAX_DOM_ELEMENTS; } @@ -5050,7 +5127,7 @@ static audit(artifacts,context){ const stats=artifacts.DOMStats; const score=Audit.computeLogNormalScore( -stats.totalDOMNodes, +stats.totalBodyElements, context.options.scorePODR, context.options.scoreMedian); @@ -5065,9 +5142,9 @@ const headings=[ const items=[ { -statistic:str_(UIStrings.statisticDOMNodes), +statistic:str_(UIStrings.statisticDOMElements), element:'', -value:Util.formatNumber(stats.totalDOMNodes)}, +value:Util.formatNumber(stats.totalBodyElements)}, { statistic:str_(UIStrings.statisticDOMDepth), @@ -5089,8 +5166,8 @@ value:Util.formatNumber(stats.width.max)}]; return{ score, -rawValue:stats.totalDOMNodes, -displayValue:str_(UIStrings.displayValue,{itemCount:stats.totalDOMNodes}), +numericValue:stats.totalBodyElements, +displayValue:str_(UIStrings.displayValue,{itemCount:stats.totalBodyElements}), extendedInfo:{ value:items}, @@ -5103,7 +5180,7 @@ module.exports=DOMSize; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/dobetterweb/dom-size.js"); -},{"../../lib/i18n/i18n.js":63,"../../report/html/renderer/util.js":80,"../audit":3}],"../audits/dobetterweb/external-anchors-use-rel-noopener":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../report/html/renderer/util.js":85,"../audit.js":3}],"../audits/dobetterweb/external-anchors-use-rel-noopener":[function(require,module,exports){ @@ -5111,8 +5188,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const URL=require('../../lib/url-shim'); -const Audit=require('../audit'); +const URL=require('../../lib/url-shim.js'); +const Audit=require('../audit.js'); class ExternalAnchorsUseRelNoopenerAudit extends Audit{ @@ -5173,7 +5250,7 @@ const headings=[ const details=Audit.makeTableDetails(headings,failingAnchors); return{ -rawValue:failingAnchors.length===0, +score:Number(failingAnchors.length===0), extendedInfo:{ value:failingAnchors}, @@ -5185,7 +5262,7 @@ warnings}; module.exports=ExternalAnchorsUseRelNoopenerAudit; -},{"../../lib/url-shim":"url","../audit":3}],"../audits/dobetterweb/geolocation-on-start":[function(require,module,exports){ +},{"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/dobetterweb/geolocation-on-start":[function(require,module,exports){ @@ -5199,7 +5276,7 @@ module.exports=ExternalAnchorsUseRelNoopenerAudit; 'use strict'; -const ViolationAudit=require('../violation-audit'); +const ViolationAudit=require('../violation-audit.js'); class GeolocationOnStart extends ViolationAudit{ @@ -5213,7 +5290,7 @@ failureTitle:'Requests the geolocation permission on page load', description:'Users are mistrustful of or confused by sites that request their '+ 'location without context. Consider tying the request to user gestures instead. '+ '[Learn more](https://developers.google.com/web/tools/lighthouse/audits/geolocation-on-load).', -requiredArtifacts:['ChromeConsoleMessages']}; +requiredArtifacts:['ConsoleMessages']}; } @@ -5235,7 +5312,7 @@ const headings=[ const details=ViolationAudit.makeTableDetails(headings,results); return{ -rawValue:results.length===0, +score:Number(results.length===0), extendedInfo:{ value:results}, @@ -5246,7 +5323,7 @@ details}; module.exports=GeolocationOnStart; -},{"../violation-audit":7}],"../audits/dobetterweb/js-libraries":[function(require,module,exports){ +},{"../violation-audit.js":7}],"../audits/dobetterweb/js-libraries":[function(require,module,exports){ @@ -5259,7 +5336,7 @@ module.exports=GeolocationOnStart; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); class JsLibrariesAudit extends Audit{ @@ -5270,7 +5347,7 @@ return{ id:'js-libraries', title:'Detected JavaScript libraries', description:'All front-end JavaScript libraries detected on the page.', -requiredArtifacts:['JSLibraries']}; +requiredArtifacts:['Stacks']}; } @@ -5279,10 +5356,12 @@ requiredArtifacts:['JSLibraries']}; static audit(artifacts){ -const libDetails=artifacts.JSLibraries.map(lib=>({ -name:lib.name, -version:lib.version||undefined, -npm:lib.npmPkgName||undefined})); +const libDetails=artifacts.Stacks. +filter(stack=>stack.detector==='js'). +map(stack=>({ +name:stack.name, +version:stack.version, +npm:stack.npm})); @@ -5293,7 +5372,7 @@ const headings=[ const details=Audit.makeTableDetails(headings,libDetails,{}); return{ -rawValue:true, +score:1, details}; }} @@ -5301,7 +5380,7 @@ details}; module.exports=JsLibrariesAudit; -},{"../audit":3}],"../audits/dobetterweb/no-document-write":[function(require,module,exports){ +},{"../audit.js":3}],"../audits/dobetterweb/no-document-write":[function(require,module,exports){ @@ -5314,7 +5393,7 @@ module.exports=JsLibrariesAudit; 'use strict'; -const ViolationAudit=require('../violation-audit'); +const ViolationAudit=require('../violation-audit.js'); class NoDocWriteAudit extends ViolationAudit{ @@ -5328,7 +5407,7 @@ failureTitle:'Uses `document.write()`', description:'For users on slow connections, external scripts dynamically injected via '+ '`document.write()` can delay page load by tens of seconds. '+ '[Learn more](https://developers.google.com/web/tools/lighthouse/audits/document-write).', -requiredArtifacts:['ChromeConsoleMessages']}; +requiredArtifacts:['ConsoleMessages']}; } @@ -5348,7 +5427,7 @@ const headings=[ const details=ViolationAudit.makeTableDetails(headings,results); return{ -rawValue:results.length===0, +score:Number(results.length===0), extendedInfo:{ value:results}, @@ -5359,7 +5438,7 @@ details}; module.exports=NoDocWriteAudit; -},{"../violation-audit":7}],"../audits/dobetterweb/no-vulnerable-libraries":[function(require,module,exports){ +},{"../violation-audit.js":7}],"../audits/dobetterweb/no-vulnerable-libraries":[function(require,module,exports){ @@ -5374,8 +5453,8 @@ module.exports=NoDocWriteAudit; 'use strict'; -const Audit=require('../audit'); -const Sentry=require('../../lib/sentry'); +const Audit=require('../audit.js'); +const Sentry=require('../../lib/sentry.js'); const semver=require('semver'); const snykDatabase=require('../../../third-party/snyk/snapshot.json'); @@ -5398,7 +5477,7 @@ failureTitle:'Includes front-end JavaScript libraries'+ description:'Some third-party scripts may contain known security vulnerabilities '+ 'that are easily identified and exploited by attackers. '+ '[Learn more](https://developers.google.com/web/tools/lighthouse/audits/vulnerabilities).', -requiredArtifacts:['JSLibraries']}; +requiredArtifacts:['Stacks']}; } @@ -5445,7 +5524,7 @@ return version; static getVulnerabilities(normalizedVersion,lib,snykDB){ -if(!lib.npmPkgName||!snykDB.npm[lib.npmPkgName]){ +if(!lib.npm||!snykDB.npm[lib.npm]){ return[]; } @@ -5453,14 +5532,14 @@ return[]; try{ semver.satisfies(normalizedVersion,'*'); }catch(err){ -err.pkgName=lib.npmPkgName; +err.pkgName=lib.npm; Sentry.captureException(err,{level:'warning'}); return[]; } -const vulnCandidatesForLib=snykDB.npm[lib.npmPkgName]; +const vulnCandidatesForLib=snykDB.npm[lib.npm]; const matchingVulns=vulnCandidatesForLib.filter(vulnCandidate=>{ @@ -5497,12 +5576,12 @@ return sortedVulns[0].severity; static audit(artifacts){ -const foundLibraries=artifacts.JSLibraries; +const foundLibraries=artifacts.Stacks.filter(stack=>stack.detector==='js'); const snykDB=NoVulnerableLibrariesAudit.snykDB; if(!foundLibraries.length){ return{ -rawValue:true}; +score:1}; } @@ -5525,7 +5604,7 @@ highestSeverity, vulnCount, detectedLib:{ text:lib.name+'@'+version, -url:`https://snyk.io/vuln/npm:${lib.npmPkgName}?lh=${version}&utm_source=lighthouse&utm_medium=ref&utm_campaign=audit`, +url:`https://snyk.io/vuln/npm:${lib.npm}?lh=${version}&utm_source=lighthouse&utm_medium=ref&utm_campaign=audit`, type:'link'}}); @@ -5533,7 +5612,7 @@ type:'link'}}); return{ name:lib.name, -npmPkgName:lib.npmPkgName, +npmPkgName:lib.npm, version, vulns, highestSeverity}; @@ -5556,7 +5635,7 @@ const headings=[ const details=Audit.makeTableDetails(headings,vulnerabilityResults,{}); return{ -rawValue:totalVulns===0, +score:Number(totalVulns===0), displayValue, extendedInfo:{ jsLibs:libraryVulns, @@ -5569,7 +5648,7 @@ details}; module.exports=NoVulnerableLibrariesAudit; -},{"../../../third-party/snyk/snapshot.json":168,"../../lib/sentry":74,"../audit":3,"semver":158}],"../audits/dobetterweb/notification-on-start":[function(require,module,exports){ +},{"../../../third-party/snyk/snapshot.json":175,"../../lib/sentry.js":77,"../audit.js":3,"semver":163}],"../audits/dobetterweb/notification-on-start":[function(require,module,exports){ @@ -5583,7 +5662,7 @@ module.exports=NoVulnerableLibrariesAudit; 'use strict'; -const ViolationAudit=require('../violation-audit'); +const ViolationAudit=require('../violation-audit.js'); class NotificationOnStart extends ViolationAudit{ @@ -5597,7 +5676,7 @@ failureTitle:'Requests the notification permission on page load', description:'Users are mistrustful of or confused by sites that request to send '+ 'notifications without context. Consider tying the request to user gestures '+ 'instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/notifications-on-load).', -requiredArtifacts:['ChromeConsoleMessages']}; +requiredArtifacts:['ConsoleMessages']}; } @@ -5617,7 +5696,7 @@ const headings=[ const details=ViolationAudit.makeTableDetails(headings,results); return{ -rawValue:results.length===0, +score:Number(results.length===0), extendedInfo:{ value:results}, @@ -5628,7 +5707,7 @@ details}; module.exports=NotificationOnStart; -},{"../violation-audit":7}],"../audits/dobetterweb/password-inputs-can-be-pasted-into":[function(require,module,exports){ +},{"../violation-audit.js":7}],"../audits/dobetterweb/password-inputs-can-be-pasted-into":[function(require,module,exports){ @@ -5636,7 +5715,7 @@ module.exports=NotificationOnStart; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); class PasswordInputsCanBePastedIntoAudit extends Audit{ @@ -5674,7 +5753,7 @@ const headings=[ return{ -rawValue:passwordInputsWithPreventedPaste.length===0, +score:Number(passwordInputsWithPreventedPaste.length===0), extendedInfo:{ value:passwordInputsWithPreventedPaste}, @@ -5685,7 +5764,7 @@ details:Audit.makeTableDetails(headings,items)}; module.exports=PasswordInputsCanBePastedIntoAudit; -},{"../audit":3}],"../audits/dobetterweb/uses-http2":[function(require,module,exports){ +},{"../audit.js":3}],"../audits/dobetterweb/uses-http2":[function(require,module,exports){ @@ -5699,8 +5778,8 @@ module.exports=PasswordInputsCanBePastedIntoAudit; 'use strict'; -const URL=require('../../lib/url-shim'); -const Audit=require('../audit'); +const URL=require('../../lib/url-shim.js'); +const Audit=require('../audit.js'); const Util=require('../../report/html/renderer/util.js'); const NetworkRecords=require('../../computed/network-records.js'); @@ -5767,7 +5846,7 @@ const headings=[ const details=Audit.makeTableDetails(headings,resources); return{ -rawValue:resources.length===0, +score:Number(resources.length===0), displayValue:displayValue, extendedInfo:{ value:{ @@ -5782,7 +5861,7 @@ details}; module.exports=UsesHTTP2Audit; -},{"../../computed/network-records.js":31,"../../lib/url-shim":"url","../../report/html/renderer/util.js":80,"../audit":3}],"../audits/dobetterweb/uses-passive-event-listeners":[function(require,module,exports){ +},{"../../computed/network-records.js":31,"../../lib/url-shim.js":"url","../../report/html/renderer/util.js":85,"../audit.js":3}],"../audits/dobetterweb/uses-passive-event-listeners":[function(require,module,exports){ @@ -5796,7 +5875,7 @@ module.exports=UsesHTTP2Audit; 'use strict'; -const ViolationAudit=require('../violation-audit'); +const ViolationAudit=require('../violation-audit.js'); class PassiveEventsAudit extends ViolationAudit{ @@ -5810,7 +5889,7 @@ failureTitle:'Does not use passive listeners to improve scrolling performance', description:'Consider marking your touch and wheel event listeners as `passive` '+ 'to improve your page\'s scroll performance. '+ '[Learn more](https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners).', -requiredArtifacts:['ChromeConsoleMessages']}; +requiredArtifacts:['ConsoleMessages']}; } @@ -5830,7 +5909,7 @@ const headings=[ const details=ViolationAudit.makeTableDetails(headings,results); return{ -rawValue:results.length===0, +score:Number(results.length===0), extendedInfo:{ value:results}, @@ -5841,7 +5920,7 @@ details}; module.exports=PassiveEventsAudit; -},{"../violation-audit":7}],"../audits/errors-in-console":[function(require,module,exports){ +},{"../violation-audit.js":7}],"../audits/errors-in-console":[function(require,module,exports){ @@ -5854,7 +5933,7 @@ module.exports=PassiveEventsAudit; -const Audit=require('./audit'); +const Audit=require('./audit.js'); class ErrorLogs extends Audit{ @@ -5867,7 +5946,7 @@ title:'No browser errors logged to the console', description:'Errors logged to the console indicate unresolved problems. '+ 'They can come from network request failures and other browser concerns.', failureTitle:'Browser errors were logged to the console', -requiredArtifacts:['ChromeConsoleMessages','RuntimeExceptions']}; +requiredArtifacts:['ConsoleMessages','RuntimeExceptions']}; } @@ -5876,7 +5955,7 @@ requiredArtifacts:['ChromeConsoleMessages','RuntimeExceptions']}; static audit(artifacts){ -const consoleEntries=artifacts.ChromeConsoleMessages; +const consoleEntries=artifacts.ConsoleMessages; const runtimeExceptions=artifacts.RuntimeExceptions; const consoleRows= @@ -5915,7 +5994,7 @@ const numErrors=tableRows.length; return{ score:Number(numErrors===0), -rawValue:numErrors, +numericValue:numErrors, details}; }} @@ -5923,7 +6002,7 @@ details}; module.exports=ErrorLogs; -},{"./audit":3}],"../audits/final-screenshot":[function(require,module,exports){ +},{"./audit.js":3}],"../audits/final-screenshot":[function(require,module,exports){ @@ -5931,8 +6010,9 @@ module.exports=ErrorLogs; 'use strict'; -const Audit=require('./audit'); -const LHError=require('../lib/lh-error'); +const Audit=require('./audit.js'); +const LHError=require('../lib/lh-error.js'); +const TraceOfTab=require('../computed/trace-of-tab.js'); const Screenshots=require('../computed/screenshots.js'); class FinalScreenshot extends Audit{ @@ -5956,7 +6036,9 @@ requiredArtifacts:['traces']}; static async audit(artifacts,context){ const trace=artifacts.traces[Audit.DEFAULT_PASS]; +const traceOfTab=await TraceOfTab.request(trace,context); const screenshots=await Screenshots.request(trace,context); +const{navigationStart}=traceOfTab.timestamps; const finalScreenshot=screenshots[screenshots.length-1]; if(!finalScreenshot){ @@ -5964,9 +6046,10 @@ throw new LHError(LHError.errors.NO_SCREENSHOTS); } return{ -rawValue:true, +score:1, details:{ type:'screenshot', +timing:Math.round((finalScreenshot.timestamp-navigationStart)/1000), timestamp:finalScreenshot.timestamp, data:finalScreenshot.datauri}}; @@ -5976,7 +6059,7 @@ data:finalScreenshot.datauri}}; module.exports=FinalScreenshot; -},{"../computed/screenshots.js":33,"../lib/lh-error":67,"./audit":3}],"../audits/font-display":[function(require,module,exports){ +},{"../computed/screenshots.js":34,"../computed/trace-of-tab.js":36,"../lib/lh-error.js":70,"./audit.js":3}],"../audits/font-display":[function(require,module,exports){ (function(__filename){ @@ -5985,8 +6068,8 @@ module.exports=FinalScreenshot; 'use strict'; -const Audit=require('./audit'); -const URL=require('../lib/url-shim').URL; +const Audit=require('./audit.js'); +const URL=require('../lib/url-shim.js'); const PASSING_FONT_DISPLAY_REGEX=/^(block|fallback|optional|swap)$/; const CSS_URL_REGEX=/url\((.*?)\)/; const CSS_URL_GLOBAL_REGEX=new RegExp(CSS_URL_REGEX,'g'); @@ -6063,10 +6146,10 @@ return s.substr(1,s.length-2); return s; }); - for(const relativeURL of relativeURLs){ try{ -const relativeRoot=stylesheet.header.sourceURL||artifacts.URL.finalUrl; +const relativeRoot=URL.isValid(stylesheet.header.sourceURL)? +stylesheet.header.sourceURL:artifacts.URL.finalUrl; const absoluteURL=new URL(relativeURL,relativeRoot); passingURLs.add(absoluteURL.href); }catch(err){ @@ -6096,6 +6179,7 @@ filter(record=>record.resourceType==='Font'). filter(record=>!passingFontURLs.has(record.url)). filter(record=>!/^data:/.test(record.url)). +filter(record=>!/^blob:/.test(record.url)). map(record=>{ @@ -6117,7 +6201,6 @@ const details=Audit.makeTableDetails(headings,results); return{ score:Number(results.length===0), -rawValue:results.length===0, details}; }} @@ -6127,7 +6210,7 @@ module.exports=FontDisplay; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/font-display.js"); -},{"../computed/network-records.js":31,"../lib/i18n/i18n.js":63,"../lib/sentry.js":74,"../lib/url-shim":"url","./audit":3}],"../audits/image-aspect-ratio":[function(require,module,exports){ +},{"../computed/network-records.js":31,"../lib/i18n/i18n.js":66,"../lib/sentry.js":77,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/image-aspect-ratio":[function(require,module,exports){ @@ -6141,9 +6224,9 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); -const URL=require('../lib/url-shim'); +const URL=require('../lib/url-shim.js'); const THRESHOLD_PX=2; @@ -6235,7 +6318,7 @@ const headings=[ return{ -rawValue:results.length===0, +score:Number(results.length===0), warnings, details:Audit.makeTableDetails(headings,results)}; @@ -6244,7 +6327,7 @@ details:Audit.makeTableDetails(headings,results)}; module.exports=ImageAspectRatio; -},{"../lib/url-shim":"url","./audit":3}],"../audits/installable-manifest":[function(require,module,exports){ +},{"../lib/url-shim.js":"url","./audit.js":3}],"../audits/installable-manifest":[function(require,module,exports){ @@ -6348,9 +6431,9 @@ module.exports=InstallableManifest; 'use strict'; -const Audit=require('./audit'); -const URL=require('../lib/url-shim'); -const Util=require('../report/html/renderer/util'); +const Audit=require('./audit.js'); +const URL=require('../lib/url-shim.js'); +const Util=require('../report/html/renderer/util.js'); const NetworkRecords=require('../computed/network-records.js'); const SECURE_SCHEMES=['data','https','wss','blob','chrome','chrome-extension','about']; @@ -6411,7 +6494,7 @@ const headings=[ return{ -rawValue:items.length===0, +score:Number(items.length===0), displayValue, extendedInfo:{ value:items}, @@ -6424,7 +6507,7 @@ details:Audit.makeTableDetails(headings,items)}; module.exports=HTTPS; -},{"../computed/network-records.js":31,"../lib/url-shim":"url","../report/html/renderer/util":80,"./audit":3}],"../audits/load-fast-enough-for-pwa":[function(require,module,exports){ +},{"../computed/network-records.js":31,"../lib/url-shim.js":"url","../report/html/renderer/util.js":85,"./audit.js":3}],"../audits/load-fast-enough-for-pwa":[function(require,module,exports){ (function(__filename){ @@ -6440,8 +6523,8 @@ module.exports=HTTPS; const isDeepEqual=require('lodash.isequal'); -const Audit=require('./audit'); -const mobileThrottling=require('../config/constants').throttling.mobileSlow4G; +const Audit=require('./audit.js'); +const mobileThrottling=require('../config/constants.js').throttling.mobileSlow4G; const Interactive=require('../computed/metrics/interactive.js'); const i18n=require('../lib/i18n/i18n.js'); @@ -6523,7 +6606,7 @@ return{ score, displayValue, explanation, -rawValue:tti.timing}; +numericValue:tti.timing}; }} @@ -6532,7 +6615,7 @@ module.exports=LoadFastEnough4Pwa; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/load-fast-enough-for-pwa.js"); -},{"../computed/metrics/interactive.js":18,"../config/constants":40,"../lib/i18n/i18n.js":63,"./audit":3,"lodash.isequal":121}],"../audits/main-thread-tasks":[function(require,module,exports){ +},{"../computed/metrics/interactive.js":18,"../config/constants.js":43,"../lib/i18n/i18n.js":66,"./audit.js":3,"lodash.isequal":126}],"../audits/main-thread-tasks":[function(require,module,exports){ @@ -6586,7 +6669,7 @@ const tableDetails=Audit.makeTableDetails(headings,results); return{ score:1, -rawValue:results.length, +numericValue:results.length, details:tableDetails}; }} @@ -6608,8 +6691,8 @@ module.exports=MainThreadTasks; 'use strict'; -const Audit=require('./audit'); -const{taskGroups}=require('../lib/task-groups'); +const Audit=require('./audit.js'); +const{taskGroups}=require('../lib/task-groups.js'); const i18n=require('../lib/i18n/i18n.js'); const MainThreadTasks=require('../computed/main-thread-tasks.js'); @@ -6720,7 +6803,7 @@ context.options.scoreMedian); return{ score, -rawValue:totalExecutionTime, +numericValue:totalExecutionTime, displayValue:str_(i18n.UIStrings.seconds,{timeInMs:totalExecutionTime}), details:tableDetails}; @@ -6731,7 +6814,7 @@ module.exports=MainThreadWorkBreakdown; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/mainthread-work-breakdown.js"); -},{"../computed/main-thread-tasks.js":12,"../lib/i18n/i18n.js":63,"../lib/task-groups":77,"./audit":3}],"../audits/manual/pwa-cross-browser":[function(require,module,exports){ +},{"../computed/main-thread-tasks.js":12,"../lib/i18n/i18n.js":66,"../lib/task-groups.js":82,"./audit.js":3}],"../audits/manual/pwa-cross-browser":[function(require,module,exports){ @@ -6740,7 +6823,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ManualAudit=require('./manual-audit'); +const ManualAudit=require('./manual-audit.js'); @@ -6762,7 +6845,7 @@ super.partialMeta); module.exports=PWACrossBrowser; -},{"./manual-audit":5}],"../audits/manual/pwa-each-page-has-url":[function(require,module,exports){ +},{"./manual-audit.js":5}],"../audits/manual/pwa-each-page-has-url":[function(require,module,exports){ @@ -6770,7 +6853,7 @@ module.exports=PWACrossBrowser; 'use strict'; -const ManualAudit=require('./manual-audit'); +const ManualAudit=require('./manual-audit.js'); @@ -6792,7 +6875,7 @@ super.partialMeta); module.exports=PWAEachPageHasURL; -},{"./manual-audit":5}],"../audits/manual/pwa-page-transitions":[function(require,module,exports){ +},{"./manual-audit.js":5}],"../audits/manual/pwa-page-transitions":[function(require,module,exports){ @@ -6800,7 +6883,7 @@ module.exports=PWAEachPageHasURL; 'use strict'; -const ManualAudit=require('./manual-audit'); +const ManualAudit=require('./manual-audit.js'); @@ -6822,7 +6905,7 @@ super.partialMeta); module.exports=PWAPageTransitions; -},{"./manual-audit":5}],"../audits/metrics/estimated-input-latency":[function(require,module,exports){ +},{"./manual-audit.js":5}],"../audits/metrics/estimated-input-latency":[function(require,module,exports){ (function(__filename){ @@ -6831,7 +6914,7 @@ module.exports=PWAPageTransitions; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const ComputedEil=require('../../computed/metrics/estimated-input-latency.js'); @@ -6857,7 +6940,7 @@ id:'estimated-input-latency', title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:Audit.SCORING_MODES.NUMERIC, -requiredArtifacts:['traces']}; +requiredArtifacts:['traces','devtoolsLogs']}; } @@ -6892,7 +6975,7 @@ metricResult.timing, context.options.scorePODR, context.options.scoreMedian), -rawValue:metricResult.timing, +numericValue:metricResult.timing, displayValue:str_(i18n.UIStrings.ms,{timeInMs:metricResult.timing})}; }} @@ -6902,7 +6985,7 @@ module.exports=EstimatedInputLatency; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/metrics/estimated-input-latency.js"); -},{"../../computed/metrics/estimated-input-latency.js":14,"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/metrics/first-contentful-paint-3g":[function(require,module,exports){ +},{"../../computed/metrics/estimated-input-latency.js":14,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/metrics/first-contentful-paint-3g":[function(require,module,exports){ @@ -6960,7 +7043,7 @@ metricResult.timing, context.options.scorePODR, context.options.scoreMedian), -rawValue:metricResult.timing, +numericValue:metricResult.timing, displayValue:`${metricResult.timing}\xa0ms`}; }} @@ -6968,7 +7051,7 @@ displayValue:`${metricResult.timing}\xa0ms`}; module.exports=FirstContentfulPaint3G; -},{"../../computed/metrics/first-contentful-paint.js":15,"../../config/constants.js":40,"../audit.js":3}],"../audits/metrics/first-contentful-paint":[function(require,module,exports){ +},{"../../computed/metrics/first-contentful-paint.js":15,"../../config/constants.js":43,"../audit.js":3}],"../audits/metrics/first-contentful-paint":[function(require,module,exports){ (function(__filename){ @@ -6977,7 +7060,7 @@ module.exports=FirstContentfulPaint3G; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const ComputedFcp=require('../../computed/metrics/first-contentful-paint.js'); @@ -7035,7 +7118,7 @@ metricResult.timing, context.options.scorePODR, context.options.scoreMedian), -rawValue:metricResult.timing, +numericValue:metricResult.timing, displayValue:str_(i18n.UIStrings.seconds,{timeInMs:metricResult.timing})}; }} @@ -7045,7 +7128,7 @@ module.exports=FirstContentfulPaint; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/metrics/first-contentful-paint.js"); -},{"../../computed/metrics/first-contentful-paint.js":15,"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/metrics/first-cpu-idle":[function(require,module,exports){ +},{"../../computed/metrics/first-contentful-paint.js":15,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/metrics/first-cpu-idle":[function(require,module,exports){ (function(__filename){ @@ -7054,7 +7137,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const ComputedFci=require('../../computed/metrics/first-cpu-idle.js'); @@ -7079,7 +7162,7 @@ id:'first-cpu-idle', title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:Audit.SCORING_MODES.NUMERIC, -requiredArtifacts:['traces']}; +requiredArtifacts:['traces','devtoolsLogs']}; } @@ -7116,7 +7199,7 @@ metricResult.timing, context.options.scorePODR, context.options.scoreMedian), -rawValue:metricResult.timing, +numericValue:metricResult.timing, displayValue:str_(i18n.UIStrings.seconds,{timeInMs:metricResult.timing})}; }} @@ -7126,7 +7209,7 @@ module.exports=FirstCPUIdle; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/metrics/first-cpu-idle.js"); -},{"../../computed/metrics/first-cpu-idle.js":16,"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/metrics/first-meaningful-paint":[function(require,module,exports){ +},{"../../computed/metrics/first-cpu-idle.js":16,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/metrics/first-meaningful-paint":[function(require,module,exports){ (function(__filename){ @@ -7135,7 +7218,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const ComputedFmp=require('../../computed/metrics/first-meaningful-paint.js'); @@ -7159,7 +7242,7 @@ id:'first-meaningful-paint', title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:Audit.SCORING_MODES.NUMERIC, -requiredArtifacts:['traces']}; +requiredArtifacts:['traces','devtoolsLogs']}; } @@ -7196,7 +7279,7 @@ metricResult.timing, context.options.scorePODR, context.options.scoreMedian), -rawValue:metricResult.timing, +numericValue:metricResult.timing, displayValue:str_(i18n.UIStrings.seconds,{timeInMs:metricResult.timing})}; }} @@ -7206,7 +7289,7 @@ module.exports=FirstMeaningfulPaint; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/metrics/first-meaningful-paint.js"); -},{"../../computed/metrics/first-meaningful-paint.js":17,"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/metrics/interactive":[function(require,module,exports){ +},{"../../computed/metrics/first-meaningful-paint.js":17,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/metrics/interactive":[function(require,module,exports){ (function(__filename){ @@ -7215,7 +7298,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const Interactive=require('../../computed/metrics/interactive.js'); @@ -7288,7 +7371,7 @@ timeInMs, context.options.scorePODR, context.options.scoreMedian), -rawValue:timeInMs, +numericValue:timeInMs, displayValue:str_(i18n.UIStrings.seconds,{timeInMs}), extendedInfo:{ value:extendedInfo}}; @@ -7301,7 +7384,7 @@ module.exports=InteractiveMetric; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/metrics/interactive.js"); -},{"../../computed/metrics/interactive.js":18,"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/metrics/max-potential-fid":[function(require,module,exports){ +},{"../../computed/metrics/interactive.js":18,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/metrics/max-potential-fid":[function(require,module,exports){ (function(__filename){ @@ -7310,16 +7393,16 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const ComputedFid=require('../../computed/metrics/max-potential-fid.js'); -const i18n=require('../../lib/i18n/i18n'); +const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ -title:'Max Potential FID', +title:'Max Potential First Input Delay', -description:'The potential First Input Delay that your users could experience is the '+ -'duration, in milliseconds, of the longest task.'}; +description:'The maximum potential First Input Delay that your users could experience is the '+ +'duration, in milliseconds, of the longest task. [Learn more](https://developers.google.com/web/updates/2018/05/first-input-delay).'}; const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings); @@ -7339,7 +7422,7 @@ id:'max-potential-fid', title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:Audit.SCORING_MODES.NUMERIC, -requiredArtifacts:['traces']}; +requiredArtifacts:['traces','devtoolsLogs']}; } @@ -7371,7 +7454,7 @@ metricResult.timing, context.options.scorePODR, context.options.scoreMedian), -rawValue:metricResult.timing, +numericValue:metricResult.timing, displayValue:str_(i18n.UIStrings.ms,{timeInMs:metricResult.timing})}; }} @@ -7381,7 +7464,7 @@ module.exports=MaxPotentialFID; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/metrics/max-potential-fid.js"); -},{"../../computed/metrics/max-potential-fid.js":27,"../../lib/i18n/i18n":63,"../audit":3}],"../audits/metrics/speed-index":[function(require,module,exports){ +},{"../../computed/metrics/max-potential-fid.js":27,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/metrics/speed-index":[function(require,module,exports){ (function(__filename){ @@ -7390,7 +7473,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const ComputedSi=require('../../computed/metrics/speed-index.js'); @@ -7450,7 +7533,7 @@ metricResult.timing, context.options.scorePODR, context.options.scoreMedian), -rawValue:metricResult.timing, +numericValue:metricResult.timing, displayValue:str_(i18n.UIStrings.seconds,{timeInMs:metricResult.timing})}; }} @@ -7460,7 +7543,7 @@ module.exports=SpeedIndex; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/metrics/speed-index.js"); -},{"../../computed/metrics/speed-index.js":29,"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/metrics":[function(require,module,exports){ +},{"../../computed/metrics/speed-index.js":29,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/metrics":[function(require,module,exports){ @@ -7468,7 +7551,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); const TraceOfTab=require('../computed/trace-of-tab.js'); const Speedline=require('../computed/speedline.js'); const FirstContentfulPaint=require('../computed/metrics/first-contentful-paint.js'); @@ -7573,14 +7656,14 @@ metrics[key]=Math.round(value); const details={ -type:'diagnostic', +type:'debugdata', items:[metrics]}; return{ score:1, -rawValue:interactive&&interactive.timing||0, +numericValue:interactive&&interactive.timing||0, details}; }} @@ -7624,7 +7707,7 @@ details}; module.exports=Metrics; -},{"../computed/metrics/estimated-input-latency.js":14,"../computed/metrics/first-contentful-paint.js":15,"../computed/metrics/first-cpu-idle.js":16,"../computed/metrics/first-meaningful-paint.js":17,"../computed/metrics/interactive.js":18,"../computed/metrics/speed-index.js":29,"../computed/speedline.js":34,"../computed/trace-of-tab.js":35,"./audit":3}],"../audits/mixed-content":[function(require,module,exports){ +},{"../computed/metrics/estimated-input-latency.js":14,"../computed/metrics/first-contentful-paint.js":15,"../computed/metrics/first-cpu-idle.js":16,"../computed/metrics/first-meaningful-paint.js":17,"../computed/metrics/interactive.js":18,"../computed/metrics/speed-index.js":29,"../computed/speedline.js":35,"../computed/trace-of-tab.js":36,"./audit.js":3}],"../audits/mixed-content":[function(require,module,exports){ @@ -7632,9 +7715,9 @@ module.exports=Metrics; 'use strict'; -const Audit=require('./audit'); -const URL=require('../lib/url-shim'); -const Util=require('../report/html/renderer/util'); +const Audit=require('./audit.js'); +const URL=require('../lib/url-shim.js'); +const Util=require('../report/html/renderer/util.js'); const NetworkRecords=require('../computed/network-records.js'); @@ -7766,7 +7849,6 @@ const totalRecords=defaultRecords.length; const score=(secureRecords.length+0.5*upgradeableResources.length)/totalRecords; return{ -rawValue:upgradeableResources.length===0, score, displayValue:displayValue, details}; @@ -7777,7 +7859,7 @@ details}; module.exports=MixedContent; -},{"../computed/network-records.js":31,"../lib/url-shim":"url","../report/html/renderer/util":80,"./audit":3}],"../audits/network-requests":[function(require,module,exports){ +},{"../computed/network-records.js":31,"../lib/url-shim.js":"url","../report/html/renderer/util.js":85,"./audit.js":3}],"../audits/network-requests":[function(require,module,exports){ @@ -7785,8 +7867,8 @@ module.exports=MixedContent; 'use strict'; -const Audit=require('./audit'); -const URL=require('../lib/url-shim'); +const Audit=require('./audit.js'); +const URL=require('../lib/url-shim.js'); const NetworkRecords=require('../computed/network-records.js'); class NetworkRequests extends Audit{ @@ -7870,7 +7952,7 @@ const tableDetails=Audit.makeTableDetails(headings,results); return{ score:1, -rawValue:results.length, +numericValue:results.length, details:tableDetails}; }); @@ -7879,7 +7961,7 @@ details:tableDetails}; module.exports=NetworkRequests; -},{"../computed/network-records.js":31,"../lib/url-shim":"url","./audit":3}],"../audits/network-rtt":[function(require,module,exports){ +},{"../computed/network-records.js":31,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/network-rtt":[function(require,module,exports){ (function(__filename){ @@ -7952,7 +8034,7 @@ const tableDetails=Audit.makeTableDetails(headings,results); return{ score:1, -rawValue:maxRtt, +numericValue:maxRtt, displayValue:str_(i18n.UIStrings.ms,{timeInMs:maxRtt}), details:tableDetails}; @@ -7963,7 +8045,7 @@ module.exports=NetworkRTT; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/network-rtt.js"); -},{"../computed/network-analysis.js":30,"../lib/i18n/i18n.js":63,"./audit.js":3}],"../audits/network-server-latency":[function(require,module,exports){ +},{"../computed/network-analysis.js":30,"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/network-server-latency":[function(require,module,exports){ (function(__filename){ @@ -7972,7 +8054,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); const i18n=require('../lib/i18n/i18n.js'); const NetworkAnalysisComputed=require('../computed/network-analysis.js'); @@ -8035,7 +8117,7 @@ const tableDetails=Audit.makeTableDetails(headings,results); return{ score:Math.max(1-maxLatency/500,0), -rawValue:maxLatency, +numericValue:maxLatency, displayValue:str_(i18n.UIStrings.ms,{timeInMs:maxLatency}), details:tableDetails}; @@ -8046,7 +8128,7 @@ module.exports=NetworkServerLatency; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/network-server-latency.js"); -},{"../computed/network-analysis.js":30,"../lib/i18n/i18n.js":63,"./audit":3}],"../audits/offline-start-url":[function(require,module,exports){ +},{"../computed/network-analysis.js":30,"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/offline-start-url":[function(require,module,exports){ @@ -8088,7 +8170,7 @@ warnings.push('We couldn\'t read the start_url from the manifest. As a result, t const hasOfflineStartUrl=artifacts.StartUrl.statusCode===200; return{ -rawValue:hasOfflineStartUrl, +score:Number(hasOfflineStartUrl), explanation:artifacts.StartUrl.explanation, warnings}; @@ -8097,7 +8179,8 @@ warnings}; module.exports=OfflineStartUrl; -},{"./audit.js":3}],"../audits/predictive-perf":[function(require,module,exports){ +},{"./audit.js":3}],"../audits/performance-budget":[function(require,module,exports){ +(function(__filename){ @@ -8105,8 +8188,159 @@ module.exports=OfflineStartUrl; 'use strict'; -const Audit=require('./audit'); -const Util=require('../report/html/renderer/util'); +const Audit=require('./audit.js'); +const ResourceSummary=require('../computed/resource-summary.js'); +const i18n=require('../lib/i18n/i18n.js'); + +const UIStrings={ + +title:'Performance budget', + +description:'Keep the quantity and size of network requests under the targets '+ +'set by the provided performance budget. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).', + +requestCountOverBudget:`{count, plural, + =1 {1 request} + other {# requests} + }`}; + + +const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings); + + + + +class ResourceBudget extends Audit{ + + + +static get meta(){ +return{ +id:'performance-budget', +title:str_(UIStrings.title), +description:str_(UIStrings.description), +scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE, +requiredArtifacts:['devtoolsLogs','URL']}; + +} + + + + + +static getRowLabel(resourceType){ + +const strMappings={ +'total':i18n.UIStrings.totalResourceType, +'document':i18n.UIStrings.documentResourceType, +'script':i18n.UIStrings.scriptResourceType, +'stylesheet':i18n.UIStrings.stylesheetResourceType, +'image':i18n.UIStrings.imageResourceType, +'media':i18n.UIStrings.mediaResourceType, +'font':i18n.UIStrings.fontResourceType, +'other':i18n.UIStrings.otherResourceType, +'third-party':i18n.UIStrings.thirdPartyResourceType}; + +return strMappings[resourceType]; +} + + + + + + +static tableItems(budget,summary){ +const resourceTypes=Object.keys(summary); +return resourceTypes.map(resourceType=>{ +const label=str_(this.getRowLabel(resourceType)); +const requestCount=summary[resourceType].count; +const size=summary[resourceType].size; + +let sizeOverBudget; +let countOverBudget; + +if(budget.resourceSizes){ +const sizeBudget=budget.resourceSizes.find(b=>b.resourceType===resourceType); +if(sizeBudget&&size>sizeBudget.budget*1024){ +sizeOverBudget=size-sizeBudget.budget*1024; +} +} +if(budget.resourceCounts){ +const countBudget=budget.resourceCounts.find(b=>b.resourceType===resourceType); +if(countBudget&&requestCount>countBudget.budget){ +const requestDifference=requestCount-countBudget.budget; +countOverBudget=str_(UIStrings.requestCountOverBudget,{count:requestDifference}); +} +} +return{ +resourceType, +label, +requestCount, +size, +countOverBudget, +sizeOverBudget}; + +}).filter(row=>{ + +if(budget.resourceSizes){ +if(budget.resourceSizes.some(b=>b.resourceType===row.resourceType))return true; +} +if(budget.resourceCounts){ +if(budget.resourceCounts.some(b=>b.resourceType===row.resourceType))return true; +} +return false; +}).sort((a,b)=>{ +return(b.sizeOverBudget||0)-(a.sizeOverBudget||0); +}); +} + + + + + + +static async audit(artifacts,context){ +const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; +const summary=await ResourceSummary.request({devtoolsLog,URL:artifacts.URL},context); +const budget=context.settings.budgets?context.settings.budgets[0]:undefined; + +if(!budget){ +return{ +score:0, +notApplicable:true}; + +} + + +const headers=[ +{key:'label',itemType:'text',text:'Resource Type'}, +{key:'requestCount',itemType:'numeric',text:'Requests'}, +{key:'size',itemType:'bytes',text:'Transfer Size'}, +{key:'countOverBudget',itemType:'text',text:''}, +{key:'sizeOverBudget',itemType:'bytes',text:'Over Budget'}]; + + +return{ +details:Audit.makeTableDetails(headers,this.tableItems(budget,summary)), +score:1}; + +}} + + +module.exports=ResourceBudget; +module.exports.UIStrings=UIStrings; + +}).call(this,"/lighthouse-core/audits/performance-budget.js"); +},{"../computed/resource-summary.js":33,"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/predictive-perf":[function(require,module,exports){ + + + + + +'use strict'; + +const Audit=require('./audit.js'); +const Util=require('../report/html/renderer/util.js'); const LanternFcp=require('../computed/metrics/lantern-first-contentful-paint.js'); const LanternFmp=require('../computed/metrics/lantern-first-meaningful-paint.js'); @@ -8188,10 +8422,10 @@ SCORING_MEDIAN); return{ score, -rawValue:values.roughEstimateOfTTI, +numericValue:values.roughEstimateOfTTI, displayValue:Util.formatMilliseconds(values.roughEstimateOfTTI), details:{ -type:'diagnostic', +type:'debugdata', items:[values]}}; @@ -8201,7 +8435,7 @@ items:[values]}}; module.exports=PredictivePerf; -},{"../computed/metrics/lantern-estimated-input-latency.js":19,"../computed/metrics/lantern-first-contentful-paint.js":20,"../computed/metrics/lantern-first-cpu-idle.js":21,"../computed/metrics/lantern-first-meaningful-paint.js":22,"../computed/metrics/lantern-interactive.js":23,"../computed/metrics/lantern-speed-index.js":26,"../report/html/renderer/util":80,"./audit":3}],"../audits/redirects-http":[function(require,module,exports){ +},{"../computed/metrics/lantern-estimated-input-latency.js":19,"../computed/metrics/lantern-first-contentful-paint.js":20,"../computed/metrics/lantern-first-cpu-idle.js":21,"../computed/metrics/lantern-first-meaningful-paint.js":22,"../computed/metrics/lantern-interactive.js":23,"../computed/metrics/lantern-speed-index.js":26,"../report/html/renderer/util.js":85,"./audit.js":3}],"../audits/redirects-http":[function(require,module,exports){ @@ -8209,7 +8443,7 @@ module.exports=PredictivePerf; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); class RedirectsHTTP extends Audit{ @@ -8232,14 +8466,14 @@ requiredArtifacts:['HTTPRedirect']}; static audit(artifacts){ return{ -rawValue:artifacts.HTTPRedirect.value}; +score:Number(artifacts.HTTPRedirect.value)}; }} module.exports=RedirectsHTTP; -},{"./audit":3}],"../audits/redirects":[function(require,module,exports){ +},{"./audit.js":3}],"../audits/redirects":[function(require,module,exports){ (function(__filename){ @@ -8248,8 +8482,8 @@ module.exports=RedirectsHTTP; 'use strict'; -const Audit=require('./audit'); -const UnusedBytes=require('./byte-efficiency/byte-efficiency-audit'); +const Audit=require('./audit.js'); +const UnusedBytes=require('./byte-efficiency/byte-efficiency-audit.js'); const i18n=require('../lib/i18n/i18n.js'); const TraceOfTab=require('../computed/trace-of-tab.js'); const NetworkRecords=require('../computed/network-records.js'); @@ -8351,7 +8585,7 @@ const details=Audit.makeOpportunityDetails(headings,pageRedirects,totalWastedMs) return{ score:redirectRequests.length<=2?1:UnusedBytes.scoreForWastedMs(totalWastedMs), -rawValue:totalWastedMs, +numericValue:totalWastedMs, displayValue:totalWastedMs? str_(i18n.UIStrings.displayValueMsSavings,{wastedMs:totalWastedMs}): '', @@ -8369,7 +8603,114 @@ module.exports=Redirects; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/redirects.js"); -},{"../computed/main-resource.js":11,"../computed/metrics/lantern-interactive.js":23,"../computed/network-records.js":31,"../computed/trace-of-tab.js":35,"../lib/i18n/i18n.js":63,"./audit":3,"./byte-efficiency/byte-efficiency-audit":4}],"../audits/screenshot-thumbnails":[function(require,module,exports){ +},{"../computed/main-resource.js":11,"../computed/metrics/lantern-interactive.js":23,"../computed/network-records.js":31,"../computed/trace-of-tab.js":36,"../lib/i18n/i18n.js":66,"./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/resource-summary":[function(require,module,exports){ +(function(__filename){ + + + + + +'use strict'; + +const Audit=require('./audit.js'); +const ComputedResourceSummary=require('../computed/resource-summary.js'); +const i18n=require('../lib/i18n/i18n.js'); + +const UIStrings={ + +title:'Keep request counts low and transfer sizes small', + +description:'To set budgets for the quantity and size of page resources,'+ +' add a budget.json file. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).', + +displayValue:`{requestCount, plural, =1 {1 request} other {# requests}}`+ +` • { byteCount, number, bytes } KB`}; + + +const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings); + +class ResourceSummary extends Audit{ + + + +static get meta(){ +return{ +id:'resource-summary', +title:str_(UIStrings.title), +description:str_(UIStrings.description), +scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE, +requiredArtifacts:['devtoolsLogs','URL']}; + +} + + + + + + +static async audit(artifacts,context){ +const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; +const summary=await ComputedResourceSummary. +request({devtoolsLog,URL:artifacts.URL},context); + + +const headings=[ +{key:'label',itemType:'text',text:'Resource Type'}, +{key:'requestCount',itemType:'numeric',text:'Requests'}, +{key:'size',itemType:'bytes',text:'Transfer Size'}]; + + + + +const strMappings={ +'total':str_(i18n.UIStrings.totalResourceType), +'document':str_(i18n.UIStrings.documentResourceType), +'script':str_(i18n.UIStrings.scriptResourceType), +'stylesheet':str_(i18n.UIStrings.stylesheetResourceType), +'image':str_(i18n.UIStrings.imageResourceType), +'media':str_(i18n.UIStrings.mediaResourceType), +'font':str_(i18n.UIStrings.fontResourceType), +'other':str_(i18n.UIStrings.otherResourceType), +'third-party':str_(i18n.UIStrings.thirdPartyResourceType)}; + + +const types=Object.keys(summary); +const rows=types.map(type=>{ +return{ + + +resourceType:type, +label:strMappings[type], +requestCount:summary[type].count, +size:summary[type].size}; + +}); + +const thirdPartyRow=rows.find(r=>r.resourceType==='third-party')||[]; +const otherRows=rows.filter(r=>r.resourceType!=='third-party'). +sort((a,b)=>{ +return b.size-a.size; +}); +const tableItems=otherRows.concat(thirdPartyRow); + +const tableDetails=Audit.makeTableDetails(headings,tableItems); + +return{ +details:tableDetails, +score:1, +displayValue:str_(UIStrings.displayValue,{ +requestCount:summary.total.count, +byteCount:summary.total.size})}; + + +}} + + +module.exports=ResourceSummary; +module.exports.UIStrings=UIStrings; + +}).call(this,"/lighthouse-core/audits/resource-summary.js"); +},{"../computed/resource-summary.js":33,"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/screenshot-thumbnails":[function(require,module,exports){ @@ -8377,8 +8718,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); -const LHError=require('../lib/lh-error'); +const Audit=require('./audit.js'); +const LHError=require('../lib/lh-error.js'); const jpeg=require('jpeg-js'); const Speedline=require('../computed/speedline.js'); const Interactive=require('../computed/metrics/interactive.js'); @@ -8488,6 +8829,7 @@ frameForTimestamp=frame; } }); } + let base64Data; const cachedThumbnail=cachedThumbnails.get(frameForTimestamp); if(cachedThumbnail){ @@ -8501,13 +8843,12 @@ cachedThumbnails.set(frameForTimestamp,base64Data); thumbnails.push({ timing:Math.round(targetTimestamp-speedline.beginning), timestamp:targetTimestamp*1000, -data:base64Data}); +data:`data:image/jpeg;base64,${base64Data}`}); } return{ score:1, -rawValue:thumbnails.length>0, details:{ type:'filmstrip', scale:timelineEnd, @@ -8519,7 +8860,7 @@ items:thumbnails}}; module.exports=ScreenshotThumbnails; -},{"../computed/metrics/interactive.js":18,"../computed/speedline.js":34,"../lib/lh-error":67,"./audit":3,"jpeg-js":117}],"../audits/seo/canonical":[function(require,module,exports){ +},{"../computed/metrics/interactive.js":18,"../computed/speedline.js":35,"../lib/lh-error.js":70,"./audit.js":3,"jpeg-js":122}],"../audits/seo/canonical":[function(require,module,exports){ (function(__filename){ @@ -8528,8 +8869,8 @@ module.exports=ScreenshotThumbnails; 'use strict'; -const Audit=require('../audit'); -const URL=require('../../lib/url-shim'); +const Audit=require('../audit.js'); +const URL=require('../../lib/url-shim.js'); const MainResource=require('../../computed/main-resource.js'); const i18n=require('../../lib/i18n/i18n.js'); @@ -8564,19 +8905,6 @@ const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings); -function getPrimaryDomain(url){ -return url.hostname. -split('.'). -slice(-2). -join('.'); -} - - - - - - - class Canonical extends Audit{ @@ -8589,7 +8917,7 @@ id:'canonical', title:str_(UIStrings.title), failureTitle:str_(UIStrings.failureTitle), description:str_(UIStrings.description), -requiredArtifacts:['LinkElements','URL']}; +requiredArtifacts:['LinkElements','URL','devtoolsLogs']}; } @@ -8640,7 +8968,7 @@ const{uniqueCanonicalURLs,invalidCanonicalLink,relativeCanonicallink}=canonicalU if(invalidCanonicalLink){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationInvalid,{url:invalidCanonicalLink.hrefRaw})}; } @@ -8648,7 +8976,7 @@ explanation:str_(UIStrings.explanationInvalid,{url:invalidCanonicalLink.hrefRaw} if(relativeCanonicallink){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationRelative,{url:relativeCanonicallink.hrefRaw})}; } @@ -8659,7 +8987,7 @@ const canonicalURLs=Array.from(uniqueCanonicalURLs); if(canonicalURLs.length===0){ return{ -rawValue:true, +score:1, notApplicable:true}; } @@ -8667,7 +8995,7 @@ notApplicable:true}; if(canonicalURLs.length>1){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationConflict,{urlList:canonicalURLs.join(', ')})}; } @@ -8689,16 +9017,16 @@ hreflangURLs.has(canonicalURL.href)&& baseURL.href!==canonicalURL.href) { return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationPointsElsewhere,{url:baseURL.href})}; } -if(getPrimaryDomain(canonicalURL)!==getPrimaryDomain(baseURL)){ +if(!URL.rootDomainsMatch(canonicalURL,baseURL)){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationDifferentDomain,{url:canonicalURL})}; } @@ -8710,7 +9038,7 @@ canonicalURL.pathname==='/'&& baseURL.pathname!=='/') { return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationRoot)}; } @@ -8743,7 +9071,7 @@ baseURL); if(mistakeAuditProduct)return mistakeAuditProduct; return{ -rawValue:true}; +score:1}; }} @@ -8752,7 +9080,7 @@ module.exports=Canonical; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/canonical.js"); -},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","../audit":3}],"../audits/seo/font-size":[function(require,module,exports){ +},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/font-size":[function(require,module,exports){ (function(__filename){ @@ -8763,9 +9091,9 @@ module.exports.UIStrings=UIStrings; -const URL=require('../../lib/url-shim'); +const URL=require('../../lib/url-shim.js'); const i18n=require('../../lib/i18n/i18n.js'); -const Audit=require('../audit'); +const Audit=require('../audit.js'); const ComputedViewportMeta=require('../../computed/viewport-meta.js'); const MINIMAL_PERCENTAGE_OF_LEGIBLE_TEXT=60; @@ -8976,15 +9304,15 @@ static async audit(artifacts,context){ if(!artifacts.TestedAsMobileDevice){ return{ -rawValue:true, +score:1, notApplicable:true}; } -const viewportMeta=await ComputedViewportMeta.request(artifacts,context); +const viewportMeta=await ComputedViewportMeta.request(artifacts.MetaElements,context); if(!viewportMeta.isMobileOptimized){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationViewport)}; } @@ -8999,7 +9327,7 @@ artifacts.FontSize; if(totalTextLength===0){ return{ -rawValue:true}; +score:1}; } @@ -9075,7 +9403,7 @@ explanation=str_(UIStrings.explanation, } return{ -rawValue:passed, +score:Number(passed), details, displayValue, explanation}; @@ -9087,7 +9415,7 @@ module.exports=FontSize; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/font-size.js"); -},{"../../computed/viewport-meta.js":37,"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","../audit":3}],"../audits/seo/hreflang":[function(require,module,exports){ +},{"../../computed/viewport-meta.js":38,"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/hreflang":[function(require,module,exports){ (function(global,__filename){ @@ -9096,7 +9424,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const VALID_LANGS=importValidLangs(); const NO_LANGUAGE='x-default'; const i18n=require('../../lib/i18n/i18n.js'); @@ -9126,7 +9454,7 @@ const axeCache=global.axe; global.axe={utils:{}}; -require('axe-core/lib/commons/utils/valid-langs.js'); +require('axe-core/lib/core/utils/valid-langs.js'); const validLangs=global.axe.utils.validLangs(); @@ -9197,7 +9525,7 @@ const headings=[ const details=Audit.makeTableDetails(headings,invalidHreflangs); return{ -rawValue:invalidHreflangs.length===0, +score:Number(invalidHreflangs.length===0), details}; }} @@ -9207,7 +9535,7 @@ module.exports=Hreflang; module.exports.UIStrings=UIStrings; }).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{},"/lighthouse-core/audits/seo/hreflang.js"); -},{"../../lib/i18n/i18n.js":63,"../audit":3,"axe-core/lib/commons/utils/valid-langs.js":88}],"../audits/seo/http-status-code":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../audit.js":3,"axe-core/lib/core/utils/valid-langs.js":93}],"../audits/seo/http-status-code":[function(require,module,exports){ (function(__filename){ @@ -9216,7 +9544,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const MainResource=require('../../computed/main-resource.js'); const HTTP_UNSUCCESSFUL_CODE_LOW=400; const HTTP_UNSUCCESSFUL_CODE_HIGH=599; @@ -9265,13 +9593,13 @@ const statusCode=mainResource.statusCode; if(statusCode>=HTTP_UNSUCCESSFUL_CODE_LOW&& statusCode<=HTTP_UNSUCCESSFUL_CODE_HIGH){ return{ -rawValue:false, +score:0, displayValue:`${statusCode}`}; } return{ -rawValue:true}; +score:1}; }); }} @@ -9281,7 +9609,7 @@ module.exports=HTTPStatusCode; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/http-status-code.js"); -},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/seo/is-crawlable":[function(require,module,exports){ +},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/seo/is-crawlable":[function(require,module,exports){ (function(__filename){ @@ -9290,9 +9618,9 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const robotsParser=require('robots-parser'); -const URL=require('../../lib/url-shim'); +const URL=require('../../lib/url-shim.js'); const MainResource=require('../../computed/main-resource.js'); const BLOCKLIST=new Set([ 'noindex', @@ -9366,7 +9694,7 @@ id:'is-crawlable', title:str_(UIStrings.title), failureTitle:str_(UIStrings.failureTitle), description:str_(UIStrings.description), -requiredArtifacts:['MetaElements','RobotsTxt','URL']}; +requiredArtifacts:['MetaElements','RobotsTxt','URL','devtoolsLogs']}; } @@ -9424,7 +9752,7 @@ const headings=[ const details=Audit.makeTableDetails(headings,blockingDirectives); return{ -rawValue:blockingDirectives.length===0, +score:Number(blockingDirectives.length===0), details}; }); @@ -9435,7 +9763,7 @@ module.exports=IsCrawlable; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/is-crawlable.js"); -},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","../audit":3,"robots-parser":156}],"../audits/seo/link-text":[function(require,module,exports){ +},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","../audit.js":3,"robots-parser":161}],"../audits/seo/link-text":[function(require,module,exports){ (function(__filename){ @@ -9444,8 +9772,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); -const URL=require('../../lib/url-shim'); +const Audit=require('../audit.js'); +const URL=require('../../lib/url-shim.js'); const BLOCKLIST=new Set([ 'click here', @@ -9463,7 +9791,26 @@ const BLOCKLIST=new Set([ 'リンク', '続きを読む', '続く', -'全文表示']); +'全文表示', + +'click aquí', +'click aqui', +'clicka aquí', +'clicka aqui', +'pincha aquí', +'pincha aqui', +'aquí', +'aqui', +'más', +'mas', +'más información', +'más informacion', +'mas información', +'mas informacion', +'este', +'enlace', +'este enlace', +'empezar']); const i18n=require('../../lib/i18n/i18n.js'); @@ -9538,7 +9885,7 @@ displayValue=str_(UIStrings.displayValue,{itemCount:failingLinks.length}); } return{ -rawValue:failingLinks.length===0, +score:Number(failingLinks.length===0), details, displayValue}; @@ -9549,7 +9896,7 @@ module.exports=LinkText; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/link-text.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","../audit":3}],"../audits/seo/manual/structured-data":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/manual/structured-data":[function(require,module,exports){ (function(__filename){ @@ -9558,7 +9905,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const ManualAudit=require('../../manual/manual-audit'); +const ManualAudit=require('../../manual/manual-audit.js'); const i18n=require('../../../lib/i18n/i18n.js'); const UIStrings={ @@ -9591,7 +9938,7 @@ module.exports=StructuredData; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/manual/structured-data.js"); -},{"../../../lib/i18n/i18n.js":63,"../../manual/manual-audit":5}],"../audits/seo/meta-description":[function(require,module,exports){ +},{"../../../lib/i18n/i18n.js":66,"../../manual/manual-audit.js":5}],"../audits/seo/meta-description":[function(require,module,exports){ (function(__filename){ @@ -9600,7 +9947,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -9640,20 +9987,20 @@ static audit(artifacts){ const metaDescription=artifacts.MetaElements.find(meta=>meta.name==='description'); if(!metaDescription){ return{ -rawValue:false}; +score:0}; } const description=metaDescription.content||''; if(description.trim().length===0){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanation)}; } return{ -rawValue:true}; +score:1}; }} @@ -9662,7 +10009,7 @@ module.exports=Description; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/meta-description.js"); -},{"../../lib/i18n/i18n.js":63,"../audit":3}],"../audits/seo/plugins":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../audit.js":3}],"../audits/seo/plugins":[function(require,module,exports){ (function(__filename){ @@ -9671,8 +10018,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('../audit'); -const URL=require('../../lib/url-shim'); +const Audit=require('../audit.js'); +const URL=require('../../lib/url-shim.js'); const JAVA_APPLET_TYPE='application/x-java-applet'; const JAVA_BEAN_TYPE='application/x-java-bean'; @@ -9826,7 +10173,7 @@ const headings=[ const details=Audit.makeTableDetails(headings,plugins); return{ -rawValue:plugins.length===0, +score:Number(plugins.length===0), details}; }} @@ -9836,7 +10183,7 @@ module.exports=Plugins; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/plugins.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","../audit":3}],"../audits/seo/robots-txt":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/robots-txt":[function(require,module,exports){ (function(__filename){ @@ -9852,8 +10199,8 @@ module.exports.UIStrings=UIStrings; -const Audit=require('../audit'); -const URL=require('../../lib/url-shim'); +const Audit=require('../audit.js'); +const URL=require('../../lib/url-shim.js'); const HTTP_CLIENT_ERROR_CODE_LOW=400; const HTTP_SERVER_ERROR_CODE_LOW=500; @@ -10042,19 +10389,19 @@ artifacts.RobotsTxt; if(!status){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanation)}; } if(status>=HTTP_SERVER_ERROR_CODE_LOW){ return{ -rawValue:false, +score:0, displayValue:str_(UIStrings.displayValueHttpBadCode,{statusCode:status})}; }else if(status>=HTTP_CLIENT_ERROR_CODE_LOW||content===''){ return{ -rawValue:true, +score:1, notApplicable:true}; } @@ -10082,7 +10429,7 @@ str_(UIStrings.displayValueValidationError,{itemCount:validationErrors.length}); } return{ -rawValue:validationErrors.length===0, +score:Number(validationErrors.length===0), details, displayValue}; @@ -10093,7 +10440,7 @@ module.exports=RobotsTxt; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/robots-txt.js"); -},{"../../lib/i18n/i18n.js":63,"../../lib/url-shim":"url","../audit":3}],"../audits/seo/tap-targets":[function(require,module,exports){ +},{"../../lib/i18n/i18n.js":66,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/tap-targets":[function(require,module,exports){ (function(__filename){ @@ -10106,7 +10453,7 @@ module.exports.UIStrings=UIStrings; -const Audit=require('../audit'); +const Audit=require('../audit.js'); const ComputedViewportMeta=require('../../computed/viewport-meta.js'); const{ rectsTouchOrOverlap, @@ -10115,8 +10462,8 @@ getRectAtCenter, allRectsContainedWithinEachOther, getLargestRect, getBoundingRectWithPadding}= -require('../../lib/rect-helpers'); -const{getTappableRectsFromClientRects}=require('../../lib/tappable-rects'); +require('../../lib/rect-helpers.js'); +const{getTappableRectsFromClientRects}=require('../../lib/tappable-rects.js'); const i18n=require('../../lib/i18n/i18n.js'); const UIStrings={ @@ -10347,7 +10694,8 @@ return{ type:'node', snippet:target.snippet, path:target.path, -selector:target.selector}; +selector:target.selector, +nodeLabel:target.nodeLabel}; } @@ -10375,15 +10723,15 @@ if(!artifacts.TestedAsMobileDevice){ return{ -rawValue:true, +score:1, notApplicable:true}; } -const viewportMeta=await ComputedViewportMeta.request(artifacts,context); +const viewportMeta=await ComputedViewportMeta.request(artifacts.MetaElements,context); if(!viewportMeta.isMobileOptimized){ return{ -rawValue:false, +score:0, explanation:str_(UIStrings.explanationViewportMetaNotOptimized)}; } @@ -10420,7 +10768,6 @@ score=passingTapTargetRatio*0.89; const displayValue=str_(UIStrings.displayValue,{decimalProportion:passingTapTargetRatio}); return{ -rawValue:tableItems.length===0, score, details, displayValue}; @@ -10465,7 +10812,7 @@ module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/seo/tap-targets.js"); -},{"../../computed/viewport-meta.js":37,"../../lib/i18n/i18n.js":63,"../../lib/rect-helpers":73,"../../lib/tappable-rects":76,"../audit":3}],"../audits/service-worker":[function(require,module,exports){ +},{"../../computed/viewport-meta.js":38,"../../lib/i18n/i18n.js":66,"../../lib/rect-helpers.js":76,"../../lib/tappable-rects.js":81,"../audit.js":3}],"../audits/service-worker":[function(require,module,exports){ @@ -10562,7 +10909,7 @@ const{versions,registrations}=artifacts.ServiceWorker; const versionsForOrigin=ServiceWorker.getVersionsForOrigin(versions,pageUrl); if(versionsForOrigin.length===0){ return{ -rawValue:false}; +score:0}; } @@ -10570,7 +10917,7 @@ const controllingScopeUrl=ServiceWorker.getControllingScopeUrl(versionsForOrigin registrations,pageUrl); if(!controllingScopeUrl){ return{ -rawValue:false, +score:0, explanation:`This origin has one or more service workers, however the page ("${pageUrl.href}") is not in scope.`}; } @@ -10579,14 +10926,14 @@ const startUrlFailure=ServiceWorker.checkStartUrl(artifacts.WebAppManifest, controllingScopeUrl); if(startUrlFailure){ return{ -rawValue:false, +score:0, explanation:`This page is controlled by a service worker, however ${startUrlFailure}.`}; } return{ -rawValue:true}; +score:1}; }} @@ -10601,7 +10948,7 @@ module.exports=ServiceWorker; 'use strict'; -const MultiCheckAudit=require('./multi-check-audit'); +const MultiCheckAudit=require('./multi-check-audit.js'); const ManifestValues=require('../computed/manifest-values.js'); @@ -10680,7 +11027,7 @@ manifestValues}; module.exports=SplashScreen; -},{"../computed/manifest-values.js":13,"./multi-check-audit":6}],"../audits/themed-omnibox":[function(require,module,exports){ +},{"../computed/manifest-values.js":13,"./multi-check-audit.js":6}],"../audits/themed-omnibox":[function(require,module,exports){ @@ -10688,7 +11035,7 @@ module.exports=SplashScreen; 'use strict'; -const MultiCheckAudit=require('./multi-check-audit'); +const MultiCheckAudit=require('./multi-check-audit.js'); const ManifestValues=require('../computed/manifest-values.js'); const cssParsers=require('cssstyle/lib/parsers'); @@ -10777,7 +11124,7 @@ themeColor:themeColorMeta&&themeColorMeta.content||null}; module.exports=ThemedOmnibox; -},{"../computed/manifest-values.js":13,"./multi-check-audit":6,"cssstyle/lib/parsers":97}],"../audits/time-to-first-byte":[function(require,module,exports){ +},{"../computed/manifest-values.js":13,"./multi-check-audit.js":6,"cssstyle/lib/parsers":102}],"../audits/time-to-first-byte":[function(require,module,exports){ (function(__filename){ @@ -10786,7 +11133,7 @@ module.exports=ThemedOmnibox; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); const i18n=require('../lib/i18n/i18n.js'); const MainResource=require('../computed/main-resource.js'); @@ -10850,7 +11197,7 @@ items:[]}; return{ -rawValue:ttfb, +numericValue:ttfb, score:Number(passed), displayValue, details, @@ -10867,7 +11214,7 @@ module.exports=TTFBMetric; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/time-to-first-byte.js"); -},{"../computed/main-resource.js":11,"../lib/i18n/i18n.js":63,"./audit":3}],"../audits/user-timings":[function(require,module,exports){ +},{"../computed/main-resource.js":11,"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/user-timings":[function(require,module,exports){ (function(__filename){ @@ -10876,7 +11223,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); const i18n=require('../lib/i18n/i18n.js'); const ComputedUserTimings=require('../computed/user-timings.js'); @@ -10984,7 +11331,7 @@ displayValue=str_(UIStrings.displayValue,{itemCount:userTimings.length}); return{ -rawValue:userTimings.length===0, +score:Number(userTimings.length===0), notApplicable:userTimings.length===0, displayValue, extendedInfo:{ @@ -11000,7 +11347,7 @@ module.exports=UserTimings; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/user-timings.js"); -},{"../computed/user-timings.js":36,"../lib/i18n/i18n.js":63,"./audit":3}],"../audits/uses-rel-preconnect":[function(require,module,exports){ +},{"../computed/user-timings.js":37,"../lib/i18n/i18n.js":66,"./audit.js":3}],"../audits/uses-rel-preconnect":[function(require,module,exports){ (function(__filename){ @@ -11010,8 +11357,8 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); -const UnusedBytes=require('./byte-efficiency/byte-efficiency-audit'); +const Audit=require('./audit.js'); +const UnusedBytes=require('./byte-efficiency/byte-efficiency-audit.js'); const URL=require('../lib/url-shim.js'); const i18n=require('../lib/i18n/i18n.js'); const NetworkRecords=require('../computed/network-records.js'); @@ -11192,7 +11539,7 @@ const details=Audit.makeOpportunityDetails(headings,results,maxWasted); return{ score:UnusedBytes.scoreForWastedMs(maxWasted), -rawValue:maxWasted, +numericValue:maxWasted, displayValue:maxWasted? str_(i18n.UIStrings.displayValueMsSavings,{wastedMs:maxWasted}): '', @@ -11209,7 +11556,7 @@ module.exports=UsesRelPreconnectAudit; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/uses-rel-preconnect.js"); -},{"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/network-records.js":31,"../lib/i18n/i18n.js":63,"../lib/url-shim.js":"url","./audit":3,"./byte-efficiency/byte-efficiency-audit":4}],"../audits/uses-rel-preload":[function(require,module,exports){ +},{"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/network-records.js":31,"../lib/i18n/i18n.js":66,"../lib/url-shim.js":"url","./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/uses-rel-preload":[function(require,module,exports){ (function(__filename){ @@ -11218,9 +11565,9 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const URL=require('../lib/url-shim'); -const Audit=require('./audit'); -const UnusedBytes=require('./byte-efficiency/byte-efficiency-audit'); +const URL=require('../lib/url-shim.js'); +const Audit=require('./audit.js'); +const UnusedBytes=require('./byte-efficiency/byte-efficiency-audit.js'); const CriticalRequestChains=require('../computed/critical-request-chains.js'); const i18n=require('../lib/i18n/i18n.js'); const MainResource=require('../computed/main-resource.js'); @@ -11435,7 +11782,7 @@ const details=Audit.makeOpportunityDetails(headings,results,wastedMs); return{ score:UnusedBytes.scoreForWastedMs(wastedMs), -rawValue:wastedMs, +numericValue:wastedMs, displayValue:wastedMs? str_(i18n.UIStrings.displayValueMsSavings,{wastedMs}): '', @@ -11452,7 +11799,7 @@ module.exports=UsesRelPreloadAudit; module.exports.UIStrings=UIStrings; }).call(this,"/lighthouse-core/audits/uses-rel-preload.js"); -},{"../computed/critical-request-chains.js":9,"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/page-dependency-graph.js":32,"../lib/i18n/i18n.js":63,"../lib/url-shim":"url","./audit":3,"./byte-efficiency/byte-efficiency-audit":4}],"../audits/viewport":[function(require,module,exports){ +},{"../computed/critical-request-chains.js":9,"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/page-dependency-graph.js":32,"../lib/i18n/i18n.js":66,"../lib/url-shim.js":"url","./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/viewport":[function(require,module,exports){ @@ -11460,7 +11807,7 @@ module.exports.UIStrings=UIStrings; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); const ComputedViewportMeta=require('../computed/viewport-meta.js'); class Viewport extends Audit{ @@ -11485,17 +11832,17 @@ requiredArtifacts:['MetaElements']}; static async audit(artifacts,context){ -const viewportMeta=await ComputedViewportMeta.request(artifacts,context); +const viewportMeta=await ComputedViewportMeta.request(artifacts.MetaElements,context); if(!viewportMeta.hasViewportTag){ return{ -rawValue:false, +score:0, explanation:'No viewport meta tag found'}; } return{ -rawValue:viewportMeta.isMobileOptimized, +score:Number(viewportMeta.isMobileOptimized), warnings:viewportMeta.parserWarnings}; }} @@ -11503,7 +11850,7 @@ warnings:viewportMeta.parserWarnings}; module.exports=Viewport; -},{"../computed/viewport-meta.js":37,"./audit":3}],"../audits/without-javascript":[function(require,module,exports){ +},{"../computed/viewport-meta.js":38,"./audit.js":3}],"../audits/without-javascript":[function(require,module,exports){ @@ -11511,7 +11858,7 @@ module.exports=Viewport; 'use strict'; -const Audit=require('./audit'); +const Audit=require('./audit.js'); class WithoutJavaScript extends Audit{ @@ -11539,20 +11886,20 @@ const artifact=artifacts.HTMLWithoutJavaScript; if(artifact.bodyText.trim()===''&&!artifact.hasNoScript){ return{ -rawValue:false, +score:0, explanation:'The page body should render some content if its scripts are not available.'}; } return{ -rawValue:true}; +score:1}; }} module.exports=WithoutJavaScript; -},{"./audit":3}],"../audits/works-offline":[function(require,module,exports){ +},{"./audit.js":3}],"../audits/works-offline":[function(require,module,exports){ @@ -11560,8 +11907,8 @@ module.exports=WithoutJavaScript; 'use strict'; -const URL=require('../lib/url-shim'); -const Audit=require('./audit'); +const URL=require('../lib/url-shim.js'); +const Audit=require('./audit.js'); class WorksOffline extends Audit{ @@ -11594,7 +11941,7 @@ warnings.push('You may be not loading offline because your test URL '+ } return{ -rawValue:passed, +score:Number(passed), warnings}; }} @@ -11602,7 +11949,7 @@ warnings}; module.exports=WorksOffline; -},{"../lib/url-shim":"url","./audit":3}],"../gather/gatherers/accessibility":[function(require,module,exports){ +},{"../lib/url-shim.js":"url","./audit.js":3}],"../gather/gatherers/accessibility":[function(require,module,exports){ @@ -11612,10 +11959,10 @@ module.exports=WorksOffline; -const Gatherer=require('./gatherer'); +const Gatherer=require('./gatherer.js'); -const axeLibSource="/*! aXe v3.1.2\n * Copyright (c) 2018 Deque Systems, Inc.\n *\n * Your use of this Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n *\n * This entire copyright notice must appear in every copy of this file you\n * distribute or in any file that contains substantial portions of this source\n * code.\n */\n!function e(window){var document=window.document,T=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};function c(e){this.name=\"SupportError\",this.cause=e.cause,this.message=\"`\"+e.cause+\"` - feature unsupported in your environment.\",e.ruleId&&(this.ruleId=e.ruleId,this.message+=\" Skipping \"+this.ruleId+\" rule.\"),this.stack=(new Error).stack}(axe=axe||{}).version=\"3.1.2\",\"function\"==typeof define&&define.amd&&define(\"axe-core\",[],function(){\"use strict\";return axe}),\"object\"===(\"undefined\"==typeof module?\"undefined\":T(module))&&module.exports&&\"function\"==typeof e.toString&&(axe.source=\"(\"+e.toString()+')(typeof window === \"object\" ? window : this);',module.exports=axe),\"function\"==typeof window.getComputedStyle&&(window.axe=axe),(c.prototype=Object.create(Error.prototype)).constructor=c,axe.imports={};var utils=axe.utils={},i={},p=(T=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e},Object.assign||function(e){for(var t=1;t>8-o%1*8)){if(255<(r=a.charCodeAt(o+=.75)))throw new s;t=t<<8|r}return n}},function(e,t,r){\"use strict\";var utils=r(2);e.exports=utils.isStandardBrowserEnv()?{write:function(e,t,r,a,n,o){var i=[];i.push(e+\"=\"+encodeURIComponent(t)),utils.isNumber(r)&&i.push(\"expires=\"+new Date(r).toGMTString()),utils.isString(a)&&i.push(\"path=\"+a),utils.isString(n)&&i.push(\"domain=\"+n),!0===o&&i.push(\"secure\"),document.cookie=i.join(\"; \")},read:function(e){var t=document.cookie.match(new RegExp(\"(^|;\\\\s*)(\"+e+\")=([^;]*)\"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,\"\",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},function(e,t,r){\"use strict\";var utils=r(2);function a(){this.handlers=[]}a.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},a.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},a.prototype.forEach=function(t){utils.forEach(this.handlers,function(e){null!==e&&t(e)})},e.exports=a},function(e,t,r){\"use strict\";var utils=r(2),a=r(19),n=r(20),o=r(6),i=r(21),s=r(22);function l(e){e.cancelToken&&e.cancelToken.throwIfRequested()}e.exports=function(t){return l(t),t.baseURL&&!i(t.url)&&(t.url=s(t.baseURL,t.url)),t.headers=t.headers||{},t.data=a(t.data,t.headers,t.transformRequest),t.headers=utils.merge(t.headers.common||{},t.headers[t.method]||{},t.headers||{}),utils.forEach([\"delete\",\"get\",\"head\",\"post\",\"put\",\"patch\",\"common\"],function(e){delete t.headers[e]}),(t.adapter||o.adapter)(t).then(function(e){return l(t),e.data=a(e.data,e.headers,t.transformResponse),e},function(e){return n(e)||(l(t),e&&e.response&&(e.response.data=a(e.response.data,e.response.headers,t.transformResponse))),Promise.reject(e)})}},function(e,t,r){\"use strict\";var utils=r(2);e.exports=function(t,r,e){return utils.forEach(e,function(e){t=e(t,r)}),t}},function(e,t){\"use strict\";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t){\"use strict\";e.exports=function(e){return/^([a-z][a-z\\d\\+\\-\\.]*:)?\\/\\//i.test(e)}},function(e,t){\"use strict\";e.exports=function(e,t){return t?e.replace(/\\/+$/,\"\")+\"/\"+t.replace(/^\\/+/,\"\"):e}},function(e,t){\"use strict\";function r(e){this.message=e}r.prototype.toString=function(){return\"Cancel\"+(this.message?\": \"+this.message:\"\")},r.prototype.__CANCEL__=!0,e.exports=r},function(e,t,r){\"use strict\";var a=r(23);function n(e){if(\"function\"!=typeof e)throw new TypeError(\"executor must be a function.\");var t;this.promise=new Promise(function(e){t=e});var r=this;e(function(e){r.reason||(r.reason=new a(e),t(r.reason))})}n.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},n.source=function(){var t;return{token:new n(function(e){t=e}),cancel:t}},e.exports=n},function(e,t){\"use strict\";e.exports=function(t){return function(e){return t.apply(null,e)}}}]),axe.imports.doT=function(e,t,r,a,n){var o=Function(\"return this\")(),i=o.doT;!function(){\"use strict\";var l,u={name:\"doT\",version:\"1.1.1\",templateSettings:{evaluate:/\\{\\{([\\s\\S]+?(\\}?)+)\\}\\}/g,interpolate:/\\{\\{=([\\s\\S]+?)\\}\\}/g,encode:/\\{\\{!([\\s\\S]+?)\\}\\}/g,use:/\\{\\{#([\\s\\S]+?)\\}\\}/g,useParams:/(^|[^\\w$])def(?:\\.|\\[[\\'\\\"])([\\w$\\.]+)(?:[\\'\\\"]\\])?\\s*\\:\\s*([\\w$\\.]+|\\\"[^\\\"]+\\\"|\\'[^\\']+\\'|\\{[^\\}]+\\})/g,define:/\\{\\{##\\s*([\\w\\.$]+)\\s*(\\:|=)([\\s\\S]+?)#\\}\\}/g,defineParams:/^\\s*([\\w$]+):([\\s\\S]+)/,conditional:/\\{\\{\\?(\\?)?\\s*([\\s\\S]*?)\\s*\\}\\}/g,iterate:/\\{\\{~\\s*(?:\\}\\}|([\\s\\S]+?)\\s*\\:\\s*([\\w$]+)\\s*(?:\\:\\s*([\\w$]+))?\\s*\\}\\})/g,varname:\"it\",strip:!0,append:!0,selfcontained:!1,doNotSkipEncoded:!1},template:void 0,compile:void 0,log:!0};u.encodeHTMLSource=function(e){var t={\"&\":\"&\",\"<\":\"<\",\">\":\">\",'\"':\""\",\"'\":\"'\",\"/\":\"/\"},r=e?/[&<>\"'\\/]/g:/&(?!#?\\w+;)|<|>|\"|'|\\//g;return function(e){return e?e.toString().replace(r,function(e){return t[e]||e}):\"\"}},(l=function(){return this||(0,eval)(\"this\")}()).doT=u;var c={append:{start:\"'+(\",end:\")+'\",startencode:\"'+encodeHTML(\"},split:{start:\"';out+=(\",end:\");out+='\",startencode:\"';out+=encodeHTML(\"}},d=/$^/;function m(e){return e.replace(/\\\\('|\\\\)/g,\"$1\").replace(/[\\r\\t\\n]/g,\" \")}u.template=function(e,t,r){var a,n,o=(t=t||u.templateSettings).append?c.append:c.split,i=0,s=t.use||t.define?function a(n,e,o){return(\"string\"==typeof e?e:e.toString()).replace(n.define||d,function(e,a,t,r){return 0===a.indexOf(\"def.\")&&(a=a.substring(4)),a in o||(\":\"===t?(n.defineParams&&r.replace(n.defineParams,function(e,t,r){o[a]={arg:t,text:r}}),a in o||(o[a]=r)):new Function(\"def\",\"def['\"+a+\"']=\"+r)(o)),\"\"}).replace(n.use||d,function(e,t){n.useParams&&(t=t.replace(n.useParams,function(e,t,r,a){if(o[r]&&o[r].arg&&a){var n=(r+\":\"+a).replace(/'|\\\\/g,\"_\");return o.__exp=o.__exp||{},o.__exp[n]=o[r].text.replace(new RegExp(\"(^|[^\\\\w$])\"+o[r].arg+\"([^\\\\w$])\",\"g\"),\"$1\"+a+\"$2\"),t+\"def.__exp['\"+n+\"']\"}}));var r=new Function(\"def\",\"return \"+t)(o);return r?a(n,r,o):r})}(t,e,r||{}):e;s=(\"var out='\"+(t.strip?s.replace(/(^|\\r|\\n)\\t* +| +\\t*(\\r|\\n|$)/g,\" \").replace(/\\r|\\n|\\t|\\/\\*[\\s\\S]*?\\*\\//g,\"\"):s).replace(/'|\\\\/g,\"\\\\$&\").replace(t.interpolate||d,function(e,t){return o.start+m(t)+o.end}).replace(t.encode||d,function(e,t){return a=!0,o.startencode+m(t)+o.end}).replace(t.conditional||d,function(e,t,r){return t?r?\"';}else if(\"+m(r)+\"){out+='\":\"';}else{out+='\":r?\"';if(\"+m(r)+\"){out+='\":\"';}out+='\"}).replace(t.iterate||d,function(e,t,r,a){return t?(i+=1,n=a||\"i\"+i,t=m(t),\"';var arr\"+i+\"=\"+t+\";if(arr\"+i+\"){var \"+r+\",\"+n+\"=-1,l\"+i+\"=arr\"+i+\".length-1;while(\"+n+\"t){var r=e.indexOf(\">\");e=e.substring(0,r+1)}return e}(n||\"\")),this._element=e}axe.utils.clone=function(e){\"use strict\";var t,r,a=e;if(null!==e&&\"object\"===(void 0===e?\"undefined\":T(e)))if(Array.isArray(e))for(a=[],t=0,r=e.length;t\":!0,\"?\":!0,\"@\":!0,\"[\":!0,\"\\\\\":!0,\"]\":!0,\"^\":!0,\"`\":!0,\"{\":!0,\"|\":!0,\"}\":!0,\"~\":!0},i={\"\\n\":\"\\\\n\",\"\\r\":\"\\\\r\",\"\\t\":\"\\\\t\",\"\\f\":\"\\\\f\",\"\\v\":\"\\\\v\"},y={n:\"\\n\",r:\"\\r\",t:\"\\t\",f:\"\\f\",\"\\\\\":\"\\\\\",\"'\":\"'\"},v={n:\"\\n\",r:\"\\r\",t:\"\\t\",f:\"\\f\",\"\\\\\":\"\\\\\",'\"':'\"'};function t(l,u,c,d,n,m){var p,f,h,g,b;return g=l.length,p=null,h=function(e,t){var r,a,n;for(n=\"\",u++,p=l.charAt(u);u\"),axe.utils.cssParser=r}(axe),L.prototype={get selector(){return this.spec.selector||[axe.utils.getSelector(this.element,this._options)]},get xpath(){return this.spec.xpath||[axe.utils.getXpath(this.element)]},get element(){return this._element},get fromFrame(){return this._fromFrame},toJSON:function(){\"use strict\";return{selector:this.selector,source:this.source,xpath:this.xpath}}},L.fromFrame=function(e,t,r){return e.selector.unshift(r.selector),e.xpath.unshift(r.xpath),new axe.utils.DqElement(r.element,t,e)},axe.utils.DqElement=L,axe.utils.matchesSelector=function(){\"use strict\";var r;return function(e,t){return r&&e[r]||(r=function(e){var t,r,a=[\"matches\",\"matchesSelector\",\"mozMatchesSelector\",\"webkitMatchesSelector\",\"msMatchesSelector\"],n=a.length;for(t=0;t=e.length/2}(u)?_(u):void 0}},axe.utils.getRootNode=function(e){var t=e.getRootNode&&e.getRootNode()||document;return t===e&&(t=document),t};var H,D=axe.utils.escapeSelector,M=void 0,V=[\"class\",\"style\",\"id\",\"selected\",\"checked\",\"disabled\",\"tabindex\",\"aria-checked\",\"aria-selected\",\"aria-invalid\",\"aria-activedescendant\",\"aria-busy\",\"aria-disabled\",\"aria-expanded\",\"aria-grabbed\",\"aria-pressed\",\"aria-valuenow\"],B=31;function G(e,t){var r=t.name,a=void 0;if(-1!==r.indexOf(\"href\")||-1!==r.indexOf(\"src\")){var n=axe.utils.getFriendlyUriEnd(e.getAttribute(r));if(n){var o=encodeURI(n);if(!o)return;a=D(t.name)+'$=\"'+o+'\"'}else a=D(t.name)+'=\"'+e.getAttribute(r)+'\"'}else a=D(r)+'=\"'+D(t.value)+'\"';return a}function Y(e,t){return e.count \"+o:s,i=i?i.filter(function(e){return axe.utils.matchesSelector(e,o)}):Array.from(r.querySelectorAll(o)),e=e.parentElement}while((1 \")?\":root\"+o.substring(o.indexOf(\" > \")):\":root\"}axe.utils.getSelectorData=function(e){for(var a={classes:{},tags:{},attributes:{}},n=(e=Array.isArray(e)?e:[e]).slice(),o=[],t=function(){var e=n.pop(),r=e.actualNode;if(r.querySelectorAll){var t=r.nodeName;a.tags[t]?a.tags[t]++:a.tags[t]=1,r.classList&&Array.from(r.classList).forEach(function(e){var t=D(e);a.classes[t]?a.classes[t]++:a.classes[t]=1}),r.attributes&&Array.from(r.attributes).filter(W).forEach(function(e){var t=G(r,e);t&&(a.attributes[t]?a.attributes[t]++:a.attributes[t]=1)})}for(e.children.length&&(o.push(n),n=e.children.slice());!n.length&&o.length;)n=o.pop()};n.length;)t();return a},axe.utils.getSelector=function(e){var t=1>>0,n=arguments[1],o=0;o>>0,a=2<=arguments.length?arguments[1]:void 0,n=0;nthis.length)&&-1!==this.indexOf(e,t)}),axe.utils.preloadCssom=function(e){var t,r,a=e.timeout,n=e.treeRoot,o=void 0===n?axe._tree[0]:n,i=axe.utils.uniqueArray((t=o,r=[],axe.utils.querySelectorAllFilter(t,\"*\",function(e){return!r.includes(e.shadowId)&&(r.push(e.shadowId),!0)}).map(function(e){return{shadowId:e.shadowId,root:axe.utils.getRootNode(e.actualNode)}})),[]),s=axe.utils.queue();if(!i.length)return s;var l=document.implementation.createHTMLDocument();function u(e){var t=e.data,r=e.isExternal,a=e.shadowId,n=e.root,o=l.createElement(\"style\");return o.type=\"text/css\",o.appendChild(l.createTextNode(t)),l.head.appendChild(o),{sheet:o.sheet,isExternal:r,shadowId:a,root:n}}return s.defer(function(t,e){i.reduce(function(e,r){return e.defer(function(e,t){(function(e,n,o){var i=e.root,s=e.shadowId;function l(e){var a=e.resolve,t=e.reject,r=e.url;axe.imports.axios({method:\"get\",url:r,timeout:n}).then(function(e){var t=e.data,r=o({data:t,isExternal:!0,shadowId:s,root:i});a(r)}).catch(t)}var u=axe.utils.queue(),t=i.styleSheets?Array.from(i.styleSheets):null;if(!t)return u;var r=[];return t.filter(function(e){var t=!1;return e.href&&(r.includes(e.href)?t=!0:r.push(e.href)),!Array.from(e.media).includes(\"print\")&&!t}).forEach(function(r){try{var e=r.cssRules,t=Array.from(e),a=t.filter(function(e){return e.href});if(!a.length)return void u.defer(function(e){return e({sheet:r,isExternal:!1,shadowId:s,root:i})});a.forEach(function(r){u.defer(function(e,t){l({resolve:e,reject:t,url:r.href})})});var n=t.filter(function(e){return!e.href}).reduce(function(e,t){return e.push(t.cssText),e},[]).join();u.defer(function(e){return e(o({data:n,shadowId:s,root:i,isExternal:!1}))})}catch(e){u.defer(function(e,t){l({resolve:e,reject:t,url:r.href})})}},[]),u})(r,a,u).then(e).catch(t)}),e},axe.utils.queue()).then(function(e){t(e.reduce(function(e,t){return e.concat(t)},[]))}).catch(e)}),s};T=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};axe.utils.shouldPreload=function(e){return!(!e||!e.preload)&&(\"boolean\"==typeof e.preload?e.preload:\"object\"===(void 0===(t=e.preload)?\"undefined\":T(t))&&Array.isArray(t.assets));var t},axe.utils.getPreloadConfig=function(e){var t={assets:axe.constants.preloadAssets,timeout:axe.constants.preloadAssetsTimeout};if(\"boolean\"==typeof e.preload)return t;if(!e.preload.assets.every(function(e){return axe.constants.preloadAssets.includes(e.toLowerCase())}))throw new Error(\"Requested assets, not supported. Supported assets are: \"+axe.constants.preloadAssets.join(\", \")+\".\");return t.assets=axe.utils.uniqueArray(e.preload.assets.map(function(e){return e.toLowerCase()}),[]),e.preload.timeout&&\"number\"==typeof e.preload.timeout&&!Number.isNaN(e.preload.timeout)&&(t.timeout=e.preload.timeout),t},axe.utils.preload=function(e){var t={cssom:axe.utils.preloadCssom},r=axe.utils.queue();if(!axe.utils.shouldPreload(e))return r;var a=axe.utils.getPreloadConfig(e);return a.assets.forEach(function(o){r.defer(function(n,e){t[o](a).then(function(e){var t,r,a;n((t={},r=o,a=e[0],r in t?Object.defineProperty(t,r,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[r]=a,t))}).catch(e)})}),r};T=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};function ne(n,o){\"use strict\";return function(e){var t=n[e.id]||{},r=t.messages||{},a=Object.assign({},t);delete a.messages,void 0===e.result?\"object\"===T(r.incomplete)?a.message=function(){return function(t,r){function a(e){return e.incomplete&&e.incomplete.default?e.incomplete.default:i.incompleteFallbackMessage()}if(!t||!t.missingData)return a(r);try{var e=r.incomplete[t.missingData[0].reason];if(!e)throw new Error;return e}catch(e){return\"string\"==typeof t.missingData?r.incomplete[t.missingData]:a(r)}}(e.data,r)}:a.message=r.incomplete:a.message=e.result===o?r.pass:r.fail,axe.utils.extendMetaData(e,a)}}axe.utils.publishMetaData=function(e){\"use strict\";var t=axe._audit.data.checks||{},r=axe._audit.data.rules||{},a=axe.utils.findBy(axe._audit.rules,\"id\",e.id)||{};e.tags=axe.utils.clone(a.tags||[]);var n=ne(t,!0),o=ne(t,!1);e.nodes.forEach(function(e){e.any.forEach(n),e.all.forEach(n),e.none.forEach(o)}),axe.utils.extendMetaData(e,axe.utils.clone(r[e.id]||{}))};var oe=function(){},ie=function(){};var se,le=(se=/(?=[\\-\\[\\]{}()*+?.\\\\\\^$|,#\\s])/g,function(e){return e.replace(se,\"\\\\\")}),ue=/\\\\/g;function ce(e){if(e)return e.map(function(e){var t,r,a=e.name.replace(ue,\"\"),n=(e.value||\"\").replace(ue,\"\");switch(e.operator){case\"^=\":r=new RegExp(\"^\"+le(n));break;case\"$=\":r=new RegExp(le(n)+\"$\");break;case\"~=\":r=new RegExp(\"(^|\\\\s)\"+le(n)+\"(\\\\s|$)\");break;case\"|=\":r=new RegExp(\"^\"+le(n)+\"(-|$)\");break;case\"=\":t=function(e){return n===e};break;case\"*=\":t=function(e){return e&&e.includes(n)};break;case\"!=\":t=function(e){return n!==e};break;default:t=function(e){return!!e}}return\"\"===n&&/^[*$^]=$/.test(e.operator)&&(t=function(){return!1}),t||(t=function(e){return e&&r.test(e)}),{key:a,value:n,test:t}})}function de(e){if(e)return e.map(function(e){return{value:e=e.replace(ue,\"\"),regexp:new RegExp(\"(^|\\\\s)\"+le(e)+\"(\\\\s|$)\")}})}function me(e){if(e)return e.map(function(e){var t;return\"not\"===e.name&&(t=(t=axe.utils.cssParser.parse(e.value)).selectors?t.selectors:[t],t=oe(t)),{name:e.name,expressions:t,value:e.value}})}function pe(e,t,r,a){var n={nodes:e.slice(),anyLevel:t,thisLevel:r,parentShadowId:a};return n.nodes.reverse(),n}function fe(e,t){return c=e.actualNode,d=t[0],1===c.nodeType&&(\"*\"===d.tag||c.nodeName.toLowerCase()===d.tag)&&(l=e.actualNode,!(u=t[0]).classes||u.classes.reduce(function(e,t){return e&&l.className&&l.className.match(t.regexp)},!0))&&(i=e.actualNode,!(s=t[0]).attributes||s.attributes.reduce(function(e,t){var r=i.getAttribute(t.key);return e&&null!==r&&(!t.value||t.test(r))},!0))&&(n=e.actualNode,!(o=t[0]).id||n.id===o.id)&&(r=e,!((a=t[0]).pseudos&&!a.pseudos.reduce(function(e,t){if(\"not\"===t.name)return e&&!ie([r],t.expressions,!1).length;throw new Error(\"the pseudo selector \"+t.name+\" has not yet been implemented\")},!0)));var r,a,n,o,i,s,l,u,c,d}oe=function(e){return e.map(function(e){for(var t=[],r=e.rule;r;)t.push({tag:r.tagName?r.tagName.toLowerCase():\"*\",combinator:r.nestingOperator?r.nestingOperator:\" \",id:r.id,attributes:ce(r.attrs),classes:de(r.classNames),pseudos:me(r.pseudos)}),r=r.rule;return t})},ie=function(e,t,r,a){for(var n=[],o=pe(Array.isArray(e)?e:[e],t,[],e[0].shadowId),i=[];o.nodes.length;){for(var s=o.nodes.pop(),l=[],u=[],c=o.anyLevel.slice().concat(o.thisLevel),d=!1,m=0;m\"].includes(f[0].combinator))throw new Error(\"axe.utils.querySelectorAll does not support the combinator: \"+p[1].combinator);\">\"===f[0].combinator?l.push(f):u.push(f)}!o.anyLevel.includes(p)||p[0].id&&s.shadowId!==o.parentShadowId||u.push(p)}for(s.children&&s.children.length&&r&&(n.push(o),o=pe(s.children,u,l,s.shadowId));!o.nodes.length&&n.length;)o=n.pop()}return i},axe.utils.querySelectorAll=function(e,t){return axe.utils.querySelectorAllFilter(e,t)},axe.utils.querySelectorAllFilter=function(e,t,r){e=Array.isArray(e)?e:[e];var a=axe.utils.cssParser.parse(t);return a=a.selectors?a.selectors:[a],a=oe(a),ie(e,a,!0,r)};T=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};!function(){\"use strict\";function m(){}function p(e){if(\"function\"!=typeof e)throw new TypeError(\"Queue methods require functions as arguments\")}axe.utils.queue=function(){var t,a=[],n=0,o=0,r=m,i=!1,s=function(e){t=e,setTimeout(function(){null!=t&&axe.log(\"Uncaught error (of queue)\",t)},1)},l=s;function u(t){return function(e){a[t]=e,(o-=1)||r===m||(i=!0,r(a))}}function c(e){return r=m,l(e),a}var d={defer:function(e){if(\"object\"===(void 0===e?\"undefined\":T(e))&&e.then&&e.catch){var r=e;e=function(e,t){r.then(e).catch(t)}}if(p(e),void 0===t){if(i)throw new Error(\"Queue already completed\");return a.push(e),++o,function(){for(var e=a.length;ne.clientHeight||!a&&e.scrollWidth>e.clientWidth)return{elm:e,top:e.scrollTop,left:e.scrollLeft}}(t);return r&&e.push(r),e.concat(be(t))},[])}function ye(e){\"use strict\";return e.sort(function(e,t){return axe.utils.contains(e,t)?1:-1})[0]}function ve(t,e){\"use strict\";var r=e.include&&ye(e.include.filter(function(e){return axe.utils.contains(e,t)})),a=e.exclude&&ye(e.exclude.filter(function(e){return axe.utils.contains(e,t)}));return!!(!a&&r||a&&axe.utils.contains(a,r))}function we(e,t){\"use strict\";var r;if(0===e.length)return t;e.length>>((3&t)<<3)&255;return a}}for(var s=\"function\"==typeof e.Buffer?e.Buffer:Array,n=[],o={},l=0;l<256;l++)n[l]=(l+256).toString(16).substr(1),o[n[l]]=l;function p(e,t){var r=t||0,a=n;return a[e[r++]]+a[e[r++]]+a[e[r++]]+a[e[r++]]+\"-\"+a[e[r++]]+a[e[r++]]+\"-\"+a[e[r++]]+a[e[r++]]+\"-\"+a[e[r++]]+a[e[r++]]+\"-\"+a[e[r++]]+a[e[r++]]+a[e[r++]]+a[e[r++]]+a[e[r++]]+a[e[r++]]}var u=i(),f=[1|u[0],u[1],u[2],u[3],u[4],u[5]],h=16383&(u[6]<<8|u[7]),g=0,b=0;function c(e,t,r){var a=t&&r||0;\"string\"==typeof e&&(t=\"binary\"==e?new s(16):null,e=null);var n=(e=e||{}).random||(e.rng||i)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,t)for(var o=0;o<16;o++)t[a+o]=n[o];return t||p(n)}(he=c).v1=function(e,t,r){var a=t&&r||0,n=t||[],o=null!=(e=e||{}).clockseq?e.clockseq:h,i=null!=e.msecs?e.msecs:(new Date).getTime(),s=null!=e.nsecs?e.nsecs:b+1,l=i-g+(s-b)/1e4;if(l<0&&null==e.clockseq&&(o=o+1&16383),(l<0||g>>24&255,n[a++]=u>>>16&255,n[a++]=u>>>8&255,n[a++]=255&u;var c=i/4294967296*1e4&268435455;n[a++]=c>>>8&255,n[a++]=255&c,n[a++]=c>>>24&15|16,n[a++]=c>>>16&255,n[a++]=o>>>8|128,n[a++]=255&o;for(var d=e.node||f,m=0;m<6;m++)n[a+m]=d[m];return t||p(n)},he.v4=c,he.parse=function(e,t,r){var a=t&&r||0,n=0;for(t=t||[],e.toLowerCase().replace(/[0-9a-f]{2}/g,function(e){n<16&&(t[a+n++]=o[e])});n<16;)t[a+n++]=0;return t},he.unparse=p,he.BufferClass=s}(window);T=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};axe._load({data:{rules:{accesskeys:{description:\"Ensures every accesskey attribute value is unique\",help:\"accesskey attribute value must be unique\"},\"area-alt\":{description:\"Ensures elements of image maps have alternate text\",help:\"Active elements must have alternate text\"},\"aria-allowed-attr\":{description:\"Ensures ARIA attributes are allowed for an element's role\",help:\"Elements must only use allowed ARIA attributes\"},\"aria-allowed-role\":{description:\"Ensures role attribute has an appropriate value for the element\",help:\"ARIA role must be appropriate for the element\"},\"aria-dpub-role-fallback\":{description:\"Ensures unsupported DPUB roles are only used on elements with implicit fallback roles\",help:\"Unsupported DPUB ARIA roles should be used on elements with implicit fallback roles\"},\"aria-hidden-body\":{description:\"Ensures aria-hidden='true' is not present on the document body.\",help:\"aria-hidden='true' must not be present on the document body\"},\"aria-required-attr\":{description:\"Ensures elements with ARIA roles have all required ARIA attributes\",help:\"Required ARIA attributes must be provided\"},\"aria-required-children\":{description:\"Ensures elements with an ARIA role that require child roles contain them\",help:\"Certain ARIA roles must contain particular children\"},\"aria-required-parent\":{description:\"Ensures elements with an ARIA role that require parent roles are contained by them\",help:\"Certain ARIA roles must be contained by particular parents\"},\"aria-roles\":{description:\"Ensures all elements with a role attribute use a valid value\",help:\"ARIA roles used must conform to valid values\"},\"aria-valid-attr-value\":{description:\"Ensures all ARIA attributes have valid values\",help:\"ARIA attributes must conform to valid values\"},\"aria-valid-attr\":{description:\"Ensures attributes that begin with aria- are valid ARIA attributes\",help:\"ARIA attributes must conform to valid names\"},\"audio-caption\":{description:\"Ensures