lighthouse 9.5.0-dev.20220515 → 9.5.0-dev.20220518

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.
@@ -137,7 +137,7 @@ function useExternalRenderer<T extends Element>(
137
137
  if (!ref.current) return;
138
138
 
139
139
  const root = renderCallback();
140
- ref.current.appendChild(root);
140
+ ref.current.append(root);
141
141
 
142
142
  return () => {
143
143
  if (ref.current?.contains(root)) ref.current.removeChild(root);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lighthouse",
3
- "version": "9.5.0-dev.20220515",
3
+ "version": "9.5.0-dev.20220518",
4
4
  "description": "Automated auditing, performance metrics, and best practices for the web.",
5
5
  "main": "./lighthouse-core/index.js",
6
6
  "bin": {
@@ -72,9 +72,9 @@ export class CategoryRenderer {
72
72
  }
73
73
 
74
74
  const titleEl = this.dom.find('.lh-audit__title', auditEl);
75
- titleEl.appendChild(this.dom.convertMarkdownCodeSnippets(audit.result.title));
75
+ titleEl.append(this.dom.convertMarkdownCodeSnippets(audit.result.title));
76
76
  const descEl = this.dom.find('.lh-audit__description', auditEl);
77
- descEl.appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.description));
77
+ descEl.append(this.dom.convertMarkdownLinkSnippets(audit.result.description));
78
78
 
79
79
  for (const relevantMetric of audit.relevantMetrics || []) {
80
80
  const adornEl = this.dom.createChildOf(descEl, 'span', 'lh-audit__adorn');
@@ -84,19 +84,16 @@ export class CategoryRenderer {
84
84
 
85
85
  if (audit.stackPacks) {
86
86
  audit.stackPacks.forEach(pack => {
87
- const packElm = this.dom.createElement('div');
88
- packElm.classList.add('lh-audit__stackpack');
89
-
90
- const packElmImg = this.dom.createElement('img');
91
- packElmImg.classList.add('lh-audit__stackpack__img');
87
+ const packElmImg = this.dom.createElement('img', 'lh-audit__stackpack__img');
92
88
  packElmImg.src = pack.iconDataURL;
93
89
  packElmImg.alt = pack.title;
94
- packElm.appendChild(packElmImg);
95
90
 
96
- packElm.appendChild(this.dom.convertMarkdownLinkSnippets(pack.description));
91
+ const snippets = this.dom.convertMarkdownLinkSnippets(pack.description);
92
+ const packElm = this.dom.createElement('div', 'lh-audit__stackpack');
93
+ packElm.append(packElmImg, snippets);
97
94
 
98
95
  this.dom.find('.lh-audit__stackpacks', auditEl)
99
- .appendChild(packElm);
96
+ .append(packElm);
100
97
  });
101
98
  }
102
99
 
@@ -105,12 +102,12 @@ export class CategoryRenderer {
105
102
  const elem = this.detailsRenderer.render(audit.result.details);
106
103
  if (elem) {
107
104
  elem.classList.add('lh-details');
108
- header.appendChild(elem);
105
+ header.append(elem);
109
106
  }
110
107
  }
111
108
 
112
109
  // Add chevron SVG to the end of the summary
113
- this.dom.find('.lh-chevron-container', auditEl).appendChild(this._createChevron());
110
+ this.dom.find('.lh-chevron-container', auditEl).append(this._createChevron());
114
111
  this._setRatingClass(auditEl, audit.result.score, scoreDisplayMode);
115
112
 
116
113
  if (audit.result.scoreDisplayMode === 'error') {
@@ -132,7 +129,7 @@ export class CategoryRenderer {
132
129
  const warningsEl = this.dom.createChildOf(summaryEl, 'div', 'lh-warnings');
133
130
  this.dom.createChildOf(warningsEl, 'span').textContent = strings.warningHeader;
134
131
  if (warnings.length === 1) {
135
- warningsEl.appendChild(this.dom.createTextNode(warnings.join('')));
132
+ warningsEl.append(this.dom.createTextNode(warnings.join('')));
136
133
  } else {
137
134
  const warningsUl = this.dom.createChildOf(warningsEl, 'ul');
138
135
  for (const warning of warnings) {
@@ -207,11 +204,11 @@ export class CategoryRenderer {
207
204
 
208
205
  const gaugeContainerEl = this.dom.find('.lh-score__gauge', component);
209
206
  const gaugeEl = this.renderCategoryScore(category, groupDefinitions, options);
210
- gaugeContainerEl.appendChild(gaugeEl);
207
+ gaugeContainerEl.append(gaugeEl);
211
208
 
212
209
  if (category.description) {
213
210
  const descEl = this.dom.convertMarkdownLinkSnippets(category.description);
214
- this.dom.find('.lh-category-header__description', component).appendChild(descEl);
211
+ this.dom.find('.lh-category-header__description', component).append(descEl);
215
212
  }
216
213
 
217
214
  return component;
@@ -230,13 +227,13 @@ export class CategoryRenderer {
230
227
 
231
228
  this.dom.createChildOf(auditGroupHeader, 'span', 'lh-audit-group__title')
232
229
  .textContent = group.title;
233
- groupEl.appendChild(auditGroupHeader);
230
+ groupEl.append(auditGroupHeader);
234
231
 
235
232
  let footerEl = null;
236
233
  if (group.description) {
237
234
  footerEl = this.dom.convertMarkdownLinkSnippets(group.description);
238
235
  footerEl.classList.add('lh-audit-group__description', 'lh-audit-group__footer');
239
- groupEl.appendChild(footerEl);
236
+ groupEl.append(footerEl);
240
237
  }
241
238
 
242
239
  return [groupEl, footerEl];
@@ -300,7 +297,7 @@ export class CategoryRenderer {
300
297
  renderUnexpandableClump(auditRefs, groupDefinitions) {
301
298
  const clumpElement = this.dom.createElement('div');
302
299
  const elements = this._renderGroupedAudits(auditRefs, groupDefinitions);
303
- elements.forEach(elem => clumpElement.appendChild(elem));
300
+ elements.forEach(elem => clumpElement.append(elem));
304
301
  return clumpElement;
305
302
  }
306
303
 
@@ -334,7 +331,7 @@ export class CategoryRenderer {
334
331
  if (description) {
335
332
  const descriptionEl = this.dom.convertMarkdownLinkSnippets(description);
336
333
  descriptionEl.classList.add('lh-audit-group__description', 'lh-audit-group__footer');
337
- el.appendChild(descriptionEl);
334
+ el.append(descriptionEl);
338
335
  }
339
336
 
340
337
  this.dom.find('.lh-clump-toggletext--show', el).textContent = Util.i18n.strings.show;
@@ -426,7 +423,7 @@ export class CategoryRenderer {
426
423
  const content = this.dom.find('.lh-fraction__content', tmpl);
427
424
  const text = this.dom.createElement('span');
428
425
  text.textContent = `${numPassed}/${numPassableAudits}`;
429
- content.appendChild(text);
426
+ content.append(text);
430
427
 
431
428
  let rating = Util.calculateRating(fraction);
432
429
 
@@ -530,7 +527,7 @@ export class CategoryRenderer {
530
527
  render(category, groupDefinitions = {}, options) {
531
528
  const element = this.dom.createElement('div', 'lh-category');
532
529
  element.id = category.id;
533
- element.appendChild(this.renderCategoryHeader(category, groupDefinitions, options));
530
+ element.append(this.renderCategoryHeader(category, groupDefinitions, options));
534
531
 
535
532
  // Top level clumps for audits, in order they will appear in the report.
536
533
  /** @type {Map<TopLevelClumpId, Array<LH.ReportResult.AuditRef>>} */
@@ -563,13 +560,13 @@ export class CategoryRenderer {
563
560
  if (clumpId === 'failed') {
564
561
  const clumpElem = this.renderUnexpandableClump(auditRefs, groupDefinitions);
565
562
  clumpElem.classList.add(`lh-clump--failed`);
566
- element.appendChild(clumpElem);
563
+ element.append(clumpElem);
567
564
  continue;
568
565
  }
569
566
 
570
567
  const description = clumpId === 'manual' ? category.manualDescription : undefined;
571
568
  const clumpElem = this.renderClump(clumpId, {auditRefs, description});
572
- element.appendChild(clumpElem);
569
+ element.append(clumpElem);
573
570
  }
574
571
 
575
572
  return element;
@@ -105,34 +105,33 @@ class CriticalRequestChainRenderer {
105
105
 
106
106
  // Construct lines and add spacers for sub requests.
107
107
  segment.treeMarkers.forEach(separator => {
108
- if (separator) {
109
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-vert'));
110
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker'));
111
- } else {
112
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker'));
113
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker'));
114
- }
108
+ const classSeparator = separator ?
109
+ 'lh-tree-marker lh-vert' :
110
+ 'lh-tree-marker';
111
+ treeMarkeEl.append(
112
+ dom.createElement('span', classSeparator),
113
+ dom.createElement('span', 'lh-tree-marker')
114
+ );
115
115
  });
116
116
 
117
- if (segment.isLastChild) {
118
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-up-right'));
119
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-right'));
120
- } else {
121
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-vert-right'));
122
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-right'));
123
- }
117
+ const classLastChild = segment.isLastChild ?
118
+ 'lh-tree-marker lh-up-right' :
119
+ 'lh-tree-marker lh-vert-right';
120
+ const classHasChildren = segment.hasChildren ?
121
+ 'lh-tree-marker lh-horiz-down' :
122
+ 'lh-tree-marker lh-right';
124
123
 
125
- if (segment.hasChildren) {
126
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-horiz-down'));
127
- } else {
128
- treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-right'));
129
- }
124
+ treeMarkeEl.append(
125
+ dom.createElement('span', classLastChild),
126
+ dom.createElement('span', 'lh-tree-marker lh-right'),
127
+ dom.createElement('span', classHasChildren)
128
+ );
130
129
 
131
130
  // Fill in url, host, and request size information.
132
131
  const url = segment.node.request.url;
133
132
  const linkEl = detailsRenderer.renderTextURL(url);
134
133
  const treevalEl = dom.find('.lh-crc-node__tree-value', chainEl);
135
- treevalEl.appendChild(linkEl);
134
+ treevalEl.append(linkEl);
136
135
 
137
136
  if (!segment.hasChildren) {
138
137
  const {startTime, endTime, transferSize} = segment.node.request;
@@ -141,8 +140,7 @@ class CriticalRequestChainRenderer {
141
140
  const span2 = dom.createElement('span', 'lh-crc-node__chain-duration');
142
141
  span2.textContent = Util.i18n.formatBytesToKiB(transferSize, 0.01);
143
142
 
144
- treevalEl.appendChild(span);
145
- treevalEl.appendChild(span2);
143
+ treevalEl.append(span, span2);
146
144
  }
147
145
 
148
146
  return chainEl;
@@ -158,7 +156,7 @@ class CriticalRequestChainRenderer {
158
156
  * @param {DetailsRenderer} detailsRenderer
159
157
  */
160
158
  static buildTree(dom, tmpl, segment, elem, details, detailsRenderer) {
161
- elem.appendChild(CRCRenderer.createChainNode(dom, segment, detailsRenderer));
159
+ elem.append(CRCRenderer.createChainNode(dom, segment, detailsRenderer));
162
160
  if (segment.node.children) {
163
161
  for (const key of Object.keys(segment.node.children)) {
164
162
  const childSegment = CRCRenderer.createSegment(segment.node.children, key,
@@ -119,12 +119,12 @@ export class DetailsRenderer {
119
119
  }
120
120
 
121
121
  const element = this._dom.createElement('div', 'lh-text__url');
122
- element.appendChild(this._renderLink({text: displayedPath, url}));
122
+ element.append(this._renderLink({text: displayedPath, url}));
123
123
 
124
124
  if (displayedHost) {
125
125
  const hostElem = this._renderText(displayedHost);
126
126
  hostElem.classList.add('lh-text__url-host');
127
- element.appendChild(hostElem);
127
+ element.append(hostElem);
128
128
  }
129
129
 
130
130
  if (title) {
@@ -397,7 +397,7 @@ export class DetailsRenderer {
397
397
 
398
398
  if (valueElement) {
399
399
  const classes = `lh-table-column--${heading.valueType}`;
400
- this._dom.createChildOf(rowElem, 'td', classes).appendChild(valueElement);
400
+ this._dom.createChildOf(rowElem, 'td', classes).append(valueElement);
401
401
  } else {
402
402
  // Empty cell is rendered for a column if:
403
403
  // - the pair is null
@@ -452,7 +452,7 @@ export class DetailsRenderer {
452
452
  const classes = `lh-table-column--${valueType}`;
453
453
  const labelEl = this._dom.createElement('div', 'lh-text');
454
454
  labelEl.textContent = heading.label;
455
- this._dom.createChildOf(theadTrElem, 'th', classes).appendChild(labelEl);
455
+ this._dom.createChildOf(theadTrElem, 'th', classes).append(labelEl);
456
456
  }
457
457
 
458
458
  const tbodyElem = this._dom.createChildOf(tableElem, 'tbody');
@@ -495,13 +495,13 @@ export class DetailsRenderer {
495
495
  if (item.nodeLabel) {
496
496
  const nodeLabelEl = this._dom.createElement('div');
497
497
  nodeLabelEl.textContent = item.nodeLabel;
498
- element.appendChild(nodeLabelEl);
498
+ element.append(nodeLabelEl);
499
499
  }
500
500
  if (item.snippet) {
501
501
  const snippetEl = this._dom.createElement('div');
502
502
  snippetEl.classList.add('lh-node__snippet');
503
503
  snippetEl.textContent = item.snippet;
504
- element.appendChild(snippetEl);
504
+ element.append(snippetEl);
505
505
  }
506
506
  if (item.selector) {
507
507
  element.title = item.selector;
@@ -97,7 +97,7 @@ export class DOM {
97
97
  */
98
98
  createChildOf(parentElem, elementName, className) {
99
99
  const element = this.createElement(elementName, className);
100
- parentElem.appendChild(element);
100
+ parentElem.append(element);
101
101
  return element;
102
102
  }
103
103
 
@@ -135,7 +135,7 @@ export class DOM {
135
135
  for (const segment of Util.splitMarkdownLink(text)) {
136
136
  if (!segment.isLink) {
137
137
  // Plain text segment.
138
- element.appendChild(this._document.createTextNode(segment.text));
138
+ element.append(this._document.createTextNode(segment.text));
139
139
  continue;
140
140
  }
141
141
 
@@ -153,7 +153,7 @@ export class DOM {
153
153
  a.target = '_blank';
154
154
  a.textContent = segment.text;
155
155
  this.safelySetHref(a, url.href);
156
- element.appendChild(a);
156
+ element.append(a);
157
157
  }
158
158
 
159
159
  return element;
@@ -210,9 +210,9 @@ export class DOM {
210
210
  if (segment.isCode) {
211
211
  const pre = this.createElement('code');
212
212
  pre.textContent = segment.text;
213
- element.appendChild(pre);
213
+ element.append(pre);
214
214
  } else {
215
- element.appendChild(this._document.createTextNode(segment.text));
215
+ element.append(this._document.createTextNode(segment.text));
216
216
  }
217
217
  }
218
218
 
@@ -295,7 +295,7 @@ export class DOM {
295
295
  const a = this.createElement('a');
296
296
  a.download = filename;
297
297
  this.safelySetBlobHref(a, blob);
298
- this._document.body.appendChild(a); // Firefox requires anchor to be in the DOM.
298
+ this._document.body.append(a); // Firefox requires anchor to be in the DOM.
299
299
  a.click();
300
300
 
301
301
  // cleanup.
@@ -186,7 +186,7 @@ export class ElementScreenshotRenderer {
186
186
  overlay.remove();
187
187
  return;
188
188
  }
189
- overlay.appendChild(screenshotElement);
189
+ overlay.append(screenshotElement);
190
190
  overlay.addEventListener('click', () => overlay.remove());
191
191
  });
192
192
  }
@@ -39,7 +39,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
39
39
  valueEl.textContent = audit.result.displayValue || '';
40
40
 
41
41
  const descriptionEl = this.dom.find('.lh-metric__description', tmpl);
42
- descriptionEl.appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.description));
42
+ descriptionEl.append(this.dom.convertMarkdownLinkSnippets(audit.result.description));
43
43
 
44
44
  if (audit.result.scoreDisplayMode === 'error') {
45
45
  descriptionEl.textContent = '';
@@ -179,7 +179,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
179
179
  const strings = Util.i18n.strings;
180
180
  const element = this.dom.createElement('div', 'lh-category');
181
181
  element.id = category.id;
182
- element.appendChild(this.renderCategoryHeader(category, groups, options));
182
+ element.append(this.renderCategoryHeader(category, groups, options));
183
183
 
184
184
  // Metrics.
185
185
  const metricAudits = category.auditRefs.filter(audit => audit.group === 'metrics');
@@ -204,7 +204,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
204
204
  const metricsBoxesEl = this.dom.createElement('div', 'lh-metrics-container');
205
205
  metricsGroupEl.insertBefore(metricsBoxesEl, metricsFooterEl);
206
206
  metricAudits.forEach(item => {
207
- metricsBoxesEl.appendChild(this._renderMetric(item));
207
+ metricsBoxesEl.append(this._renderMetric(item));
208
208
  });
209
209
 
210
210
  // Only add the disclaimer with the score calculator link if the category was rendered with a score gauge.
@@ -212,7 +212,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
212
212
  const descriptionEl = this.dom.find('.lh-category-header__description', element);
213
213
  const estValuesEl = this.dom.createChildOf(descriptionEl, 'div', 'lh-metrics__disclaimer');
214
214
  const disclaimerEl = this.dom.convertMarkdownLinkSnippets(strings.varianceDisclaimer);
215
- estValuesEl.appendChild(disclaimerEl);
215
+ estValuesEl.append(disclaimerEl);
216
216
 
217
217
  // Add link to score calculator.
218
218
  const calculatorLink = this.dom.createChildOf(estValuesEl, 'a', 'lh-calclink');
@@ -222,7 +222,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
222
222
  }
223
223
 
224
224
  metricsGroupEl.classList.add('lh-audit-group--metrics');
225
- element.appendChild(metricsGroupEl);
225
+ element.append(metricsGroupEl);
226
226
  }
227
227
 
228
228
  // Filmstrip
@@ -232,7 +232,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
232
232
  if (thumbnailResult?.details) {
233
233
  timelineEl.id = thumbnailResult.id;
234
234
  const filmstripEl = this.detailsRenderer.render(thumbnailResult.details);
235
- filmstripEl && timelineEl.appendChild(filmstripEl);
235
+ filmstripEl && timelineEl.append(filmstripEl);
236
236
  }
237
237
 
238
238
  // Opportunities
@@ -266,7 +266,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
266
266
  opportunityAudits.forEach(item =>
267
267
  groupEl.insertBefore(this._renderOpportunity(item, scale), footerEl));
268
268
  groupEl.classList.add('lh-audit-group--load-opportunities');
269
- element.appendChild(groupEl);
269
+ element.append(groupEl);
270
270
  }
271
271
 
272
272
  // Diagnostics
@@ -283,7 +283,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
283
283
  const [groupEl, footerEl] = this.renderAuditGroup(groups['diagnostics']);
284
284
  diagnosticAudits.forEach(item => groupEl.insertBefore(this.renderAudit(item), footerEl));
285
285
  groupEl.classList.add('lh-audit-group--diagnostics');
286
- element.appendChild(groupEl);
286
+ element.append(groupEl);
287
287
  }
288
288
 
289
289
  // Passed audits
@@ -297,7 +297,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
297
297
  groupDefinitions: groups,
298
298
  };
299
299
  const passedElem = this.renderClump('passed', clumpOpts);
300
- element.appendChild(passedElem);
300
+ element.append(passedElem);
301
301
 
302
302
  // Budgets
303
303
  /** @type {Array<Element>} */
@@ -317,7 +317,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
317
317
  const [groupEl, footerEl] = this.renderAuditGroup(groups.budgets);
318
318
  budgetTableEls.forEach(table => groupEl.insertBefore(table, footerEl));
319
319
  groupEl.classList.add('lh-audit-group--budgets');
320
- element.appendChild(groupEl);
320
+ element.append(groupEl);
321
321
  }
322
322
 
323
323
  return element;
@@ -27,7 +27,7 @@ export class PwaCategoryRenderer extends CategoryRenderer {
27
27
  render(category, groupDefinitions = {}) {
28
28
  const categoryElem = this.dom.createElement('div', 'lh-category');
29
29
  categoryElem.id = category.id;
30
- categoryElem.appendChild(this.renderCategoryHeader(category, groupDefinitions));
30
+ categoryElem.append(this.renderCategoryHeader(category, groupDefinitions));
31
31
 
32
32
  const auditRefs = category.auditRefs;
33
33
 
@@ -35,13 +35,13 @@ export class PwaCategoryRenderer extends CategoryRenderer {
35
35
  // all put in a top-level clump that isn't expandable/collapsible.
36
36
  const regularAuditRefs = auditRefs.filter(ref => ref.result.scoreDisplayMode !== 'manual');
37
37
  const auditsElem = this._renderAudits(regularAuditRefs, groupDefinitions);
38
- categoryElem.appendChild(auditsElem);
38
+ categoryElem.append(auditsElem);
39
39
 
40
40
  // Manual audits are still in a manual clump.
41
41
  const manualAuditRefs = auditRefs.filter(ref => ref.result.scoreDisplayMode === 'manual');
42
42
  const manualElem = this.renderClump('manual',
43
43
  {auditRefs: manualAuditRefs, description: category.manualDescription});
44
- categoryElem.appendChild(manualElem);
44
+ categoryElem.append(manualElem);
45
45
 
46
46
  return categoryElem;
47
47
  }
@@ -70,7 +70,7 @@ export class ReportRenderer {
70
70
  const report = Util.prepareReportResult(lhr);
71
71
 
72
72
  this._dom.rootEl.textContent = ''; // Remove previous report.
73
- this._dom.rootEl.appendChild(this._renderReport(report));
73
+ this._dom.rootEl.append(this._renderReport(report));
74
74
 
75
75
  return this._dom.rootEl;
76
76
  }
@@ -178,11 +178,13 @@ export class ReportRenderer {
178
178
  const message = this._dom.find('.lh-warnings__msg', container);
179
179
  message.textContent = Util.i18n.strings.toplevelWarningsMessage;
180
180
 
181
- const warnings = this._dom.find('ul', container);
181
+ const warnings = [];
182
182
  for (const warningString of report.runWarnings) {
183
- const warning = warnings.appendChild(this._dom.createElement('li'));
184
- warning.appendChild(this._dom.convertMarkdownLinkSnippets(warningString));
183
+ const warning = this._dom.createElement('li');
184
+ warning.append(this._dom.convertMarkdownLinkSnippets(warningString));
185
+ warnings.push(warning);
185
186
  }
187
+ this._dom.find('ul', container).append(...warnings);
186
188
 
187
189
  return container;
188
190
  }
@@ -275,11 +277,11 @@ export class ReportRenderer {
275
277
  };
276
278
 
277
279
  const headerContainer = this._dom.createElement('div');
278
- headerContainer.appendChild(this._renderReportHeader());
280
+ headerContainer.append(this._renderReportHeader());
279
281
 
280
282
  const reportContainer = this._dom.createElement('div', 'lh-container');
281
283
  const reportSection = this._dom.createElement('div', 'lh-report');
282
- reportSection.appendChild(this._renderReportWarnings(report));
284
+ reportSection.append(this._renderReportWarnings(report));
283
285
 
284
286
  let scoreHeader;
285
287
  const isSoloCategory = Object.keys(report.categories).length === 1;
@@ -296,23 +298,23 @@ export class ReportRenderer {
296
298
  const scoresContainer = this._dom.find('.lh-scores-container', headerContainer);
297
299
  scoreHeader.append(
298
300
  ...this._renderScoreGauges(report, categoryRenderer, specificCategoryRenderers));
299
- scoresContainer.appendChild(scoreHeader);
300
- scoresContainer.appendChild(scoreScale);
301
+ scoresContainer.append(scoreHeader, scoreScale);
301
302
 
302
303
  const stickyHeader = this._dom.createElement('div', 'lh-sticky-header');
303
304
  stickyHeader.append(
304
305
  ...this._renderScoreGauges(report, categoryRenderer, specificCategoryRenderers));
305
- reportContainer.appendChild(stickyHeader);
306
+ reportContainer.append(stickyHeader);
306
307
  }
307
308
 
308
- const categories = reportSection.appendChild(this._dom.createElement('div', 'lh-categories'));
309
+ const categories = this._dom.createElement('div', 'lh-categories');
310
+ reportSection.append(categories);
309
311
  const categoryOptions = {gatherMode: report.gatherMode};
310
312
  for (const category of Object.values(report.categories)) {
311
313
  const renderer = specificCategoryRenderers[category.id] || categoryRenderer;
312
314
  // .lh-category-wrapper is full-width and provides horizontal rules between categories.
313
315
  // .lh-category within has the max-width: var(--report-content-max-width);
314
316
  const wrapper = renderer.dom.createChildOf(categories, 'div', 'lh-category-wrapper');
315
- wrapper.appendChild(renderer.render(
317
+ wrapper.append(renderer.render(
316
318
  category,
317
319
  report.categoryGroups,
318
320
  categoryOptions
@@ -327,13 +329,12 @@ export class ReportRenderer {
327
329
  }
328
330
 
329
331
  if (!this._opts.omitTopbar) {
330
- reportFragment.appendChild(this._renderReportTopbar(report));
332
+ reportFragment.append(this._renderReportTopbar(report));
331
333
  }
332
334
 
333
- reportFragment.appendChild(reportContainer);
334
- reportContainer.appendChild(headerContainer);
335
- reportContainer.appendChild(reportSection);
336
- reportSection.appendChild(this._renderReportFooter(report));
335
+ reportFragment.append(reportContainer);
336
+ reportSection.append(this._renderReportFooter(report));
337
+ reportContainer.append(headerContainer, reportSection);
337
338
 
338
339
  if (fullPageScreenshot) {
339
340
  ElementScreenshotRenderer.installFullPageScreenshot(
@@ -128,7 +128,7 @@ export class SnippetRenderer {
128
128
  // access the full element detail. Just being able to see the outer HTML isn't very useful.
129
129
  if (details.node && dom.isDevTools()) {
130
130
  const nodeContainer = dom.find('.lh-snippet__node', header);
131
- nodeContainer.appendChild(detailsRenderer.renderNode(details.node));
131
+ nodeContainer.append(detailsRenderer.renderNode(details.node));
132
132
  }
133
133
 
134
134
  return header;
@@ -163,7 +163,7 @@ export class SnippetRenderer {
163
163
  const lineContent = content + (truncated ? '…' : '');
164
164
  const lineContentEl = dom.find('.lh-snippet__line code', contentLine);
165
165
  if (contentType === LineContentType.MESSAGE) {
166
- lineContentEl.appendChild(dom.convertMarkdownLinkSnippets(lineContent));
166
+ lineContentEl.append(dom.convertMarkdownLinkSnippets(lineContent));
167
167
  } else {
168
168
  lineContentEl.textContent = lineContent;
169
169
  }