lighthouse 9.2.0-dev.20211226 → 9.2.0-dev.20211230

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lighthouse",
3
- "version": "9.2.0-dev.20211226",
3
+ "version": "9.2.0-dev.20211230",
4
4
  "description": "Automated auditing, performance metrics, and best practices for the web.",
5
5
  "main": "./lighthouse-core/index.js",
6
6
  "bin": {
@@ -417,7 +417,8 @@ limitations under the License.
417
417
  <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--print" data-i18n="dropdownPrintSummary" data-action="print-summary"></a>
418
418
  <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--print" data-i18n="dropdownPrintExpanded" data-action="print-expanded"></a>
419
419
  <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--copy" data-i18n="dropdownCopyJSON" data-action="copy"></a>
420
- <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--download" data-i18n="dropdownSaveHTML" data-action="save-html"></a>
420
+ <!-- Only enabled if Options.getStandaloneReportHTML is set. -->
421
+ <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--download lh-hidden" data-i18n="dropdownSaveHTML" data-action="save-html"></a>
421
422
  <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--download" data-i18n="dropdownSaveJSON" data-action="save-json"></a>
422
423
  <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--open" data-i18n="dropdownViewer" data-action="open-viewer"></a>
423
424
  <a role="menuitem" tabindex="-1" href="#" class="lh-report-icon lh-report-icon--open" data-i18n="dropdownSaveGist" data-action="save-gist"></a>
@@ -21,7 +21,11 @@ function __initLighthouseReport__() {
21
21
  // @ts-expect-error
22
22
  const lhr = window.__LIGHTHOUSE_JSON__;
23
23
 
24
- const reportRootEl = renderReport(lhr);
24
+ const reportRootEl = renderReport(lhr, {
25
+ getStandaloneReportHTML() {
26
+ return document.documentElement.outerHTML;
27
+ },
28
+ });
25
29
  document.body.append(reportRootEl);
26
30
 
27
31
  document.addEventListener('lh-analytics', /** @param {Event} e */ e => {
@@ -706,7 +706,7 @@ function createTopbarComponent(dom) {
706
706
  el40.setAttribute('href', '#');
707
707
  el40.setAttribute('data-i18n', 'dropdownCopyJSON');
708
708
  el40.setAttribute('data-action', 'copy');
709
- const el41 = dom.createElement('a', 'lh-report-icon lh-report-icon--download');
709
+ const el41 = dom.createElement('a', 'lh-report-icon lh-report-icon--download lh-hidden');
710
710
  el41.setAttribute('role', 'menuitem');
711
711
  el41.setAttribute('tabindex', '-1');
712
712
  el41.setAttribute('href', '#');
@@ -736,7 +736,7 @@ function createTopbarComponent(dom) {
736
736
  el45.setAttribute('href', '#');
737
737
  el45.setAttribute('data-i18n', 'dropdownDarkTheme');
738
738
  el45.setAttribute('data-action', 'toggle-dark');
739
- el37.append(' ', el38, ' ', el39, ' ', el40, ' ', el41, ' ', el42, ' ', el43, ' ', el44, ' ', el45, ' ');
739
+ el37.append(' ', el38, ' ', el39, ' ', el40, ' ', ' ', el41, ' ', el42, ' ', el43, ' ', el44, ' ', el45, ' ');
740
740
  el26.append(' ', el27, ' ', el33, ' ', el37, ' ');
741
741
  el2.append(' ', ' ', el3, ' ', el25, ' ', el26, ' ');
742
742
  el0.append(el2);
@@ -112,6 +112,10 @@ export class ReportUIFeatures {
112
112
  });
113
113
  }
114
114
 
115
+ if (this._opts.getStandaloneReportHTML) {
116
+ this._dom.find('a[data-action="save-html"]', this._dom.rootEl).classList.remove('lh-hidden');
117
+ }
118
+
115
119
  // Fill in all i18n data.
116
120
  for (const node of this._dom.findAll('[data-i18n]', this._dom.rootEl)) {
117
121
  // These strings are guaranteed to (at least) have a default English string in Util.UIStrings,
@@ -146,15 +150,23 @@ export class ReportUIFeatures {
146
150
  return buttonEl;
147
151
  }
148
152
 
153
+ resetUIState() {
154
+ if (this._topbar) {
155
+ this._topbar.resetUIState();
156
+ }
157
+ }
158
+
149
159
  /**
150
160
  * Returns the html that recreates this report.
151
161
  * @return {string}
152
162
  */
153
163
  getReportHtml() {
154
- if (this._topbar) {
155
- this._topbar.resetUIState();
164
+ if (!this._opts.getStandaloneReportHTML) {
165
+ throw new Error('`getStandaloneReportHTML` is not set');
156
166
  }
157
- return `<!doctype html><body style="margin: 0">${this._dom.rootEl.outerHTML}`;
167
+
168
+ this.resetUIState();
169
+ return this._opts.getStandaloneReportHTML();
158
170
  }
159
171
 
160
172
  /**
@@ -27,15 +27,16 @@ describe('ReportUIFeatures', () => {
27
27
 
28
28
  /**
29
29
  * @param {LH.JSON} lhr
30
+ * @param {LH.Renderer.Options=} opts
30
31
  * @return {HTMLElement}
31
32
  */
32
- function render(lhr) {
33
+ function render(lhr, opts) {
33
34
  const detailsRenderer = new DetailsRenderer(dom);
34
35
  const categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
35
36
  const renderer = new ReportRenderer(dom, categoryRenderer);
36
- const reportUIFeatures = new ReportUIFeatures(dom);
37
+ const reportUIFeatures = new ReportUIFeatures(dom, opts);
37
38
  const container = dom.find('body', dom.document());
38
- renderer.renderReport(lhr, container);
39
+ renderer.renderReport(lhr, container, opts);
39
40
  reportUIFeatures.initFeatures(lhr);
40
41
  return container;
41
42
  }
@@ -60,6 +61,7 @@ describe('ReportUIFeatures', () => {
60
61
 
61
62
  global.HTMLElement = document.window.HTMLElement;
62
63
  global.HTMLInputElement = document.window.HTMLInputElement;
64
+ global.CustomEvent = document.window.CustomEvent;
63
65
 
64
66
  global.window = document.window;
65
67
  global.window.requestAnimationFrame = fn => fn();
@@ -83,6 +85,7 @@ describe('ReportUIFeatures', () => {
83
85
  global.window = undefined;
84
86
  global.HTMLElement = undefined;
85
87
  global.HTMLInputElement = undefined;
88
+ global.CustomEvent = undefined;
86
89
  });
87
90
 
88
91
  describe('initFeatures', () => {
@@ -275,6 +278,22 @@ describe('ReportUIFeatures', () => {
275
278
  expect(filterControl.hidden).toEqual(true);
276
279
  });
277
280
  });
281
+
282
+ it('save-html option enabled if callback present', () => {
283
+ let container = render(sampleResults);
284
+ const getSaveEl = () => dom.find('a[data-action="save-html"]', container);
285
+ expect(getSaveEl().classList.contains('lh-hidden')).toBeTruthy();
286
+
287
+ const getHtmlMock = jest.fn();
288
+ container = render(sampleResults, {
289
+ getStandaloneReportHTML: getHtmlMock,
290
+ });
291
+ expect(getSaveEl().classList.contains('lh-hidden')).toBeFalsy();
292
+
293
+ expect(getHtmlMock).not.toBeCalled();
294
+ getSaveEl().click();
295
+ expect(getHtmlMock).toBeCalled();
296
+ });
278
297
  });
279
298
 
280
299
  describe('fireworks', () => {
@@ -351,7 +370,6 @@ describe('ReportUIFeatures', () => {
351
370
  assert.ok(!dropDown._toggleEl.classList.contains('lh-active'));
352
371
  });
353
372
 
354
-
355
373
  it('Escape key removes active class', () => {
356
374
  dropDown._toggleEl.click();
357
375
  assert.ok(dropDown._toggleEl.classList.contains('lh-active'));
@@ -24,6 +24,8 @@ declare module Renderer {
24
24
  * Flow report uses this to convert `#seo` to `#index=0&anchor=seo`.
25
25
  */
26
26
  onPageAnchorRendered?: (link: HTMLAnchorElement) => void;
27
+ /** If defined, `Save as HTML` option is shown in dropdown menu. */
28
+ getStandaloneReportHTML?: () => string;
27
29
  }
28
30
  }
29
31