/** * Copyright (c) Microsoft Corporation. * * 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. */ import type { FrameSnapshot, NodeSnapshot, RenderedFrameSnapshot, ResourceSnapshot } from '@trace/snapshot'; export class SnapshotRenderer { private _snapshots: FrameSnapshot[]; private _index: number; readonly snapshotName: string | undefined; _resources: ResourceSnapshot[]; private _snapshot: FrameSnapshot; constructor(resources: ResourceSnapshot[], snapshots: FrameSnapshot[], index: number) { this._resources = resources; this._snapshots = snapshots; this._index = index; this._snapshot = snapshots[index]; this.snapshotName = snapshots[index].snapshotName; } snapshot(): FrameSnapshot { return this._snapshots[this._index]; } viewport(): { width: number, height: number } { return this._snapshots[this._index].viewport; } render(): RenderedFrameSnapshot { const visit = (n: NodeSnapshot, snapshotIndex: number, parentTag: string | undefined): string => { // Text node. if (typeof n === 'string') { const text = escapeText(n); // Best-effort Electron support: rewrite custom protocol in url() links in stylesheets. // Old snapshotter was sending lower-case. if (parentTag === 'STYLE' || parentTag === 'style') return rewriteURLsInStyleSheetForCustomProtocol(text); return text; } if (!(n as any)._string) { if (Array.isArray(n[0])) { // Node reference. const referenceIndex = snapshotIndex - n[0][0]; if (referenceIndex >= 0 && referenceIndex <= snapshotIndex) { const nodes = snapshotNodes(this._snapshots[referenceIndex]); const nodeIndex = n[0][1]; if (nodeIndex >= 0 && nodeIndex < nodes.length) (n as any)._string = visit(nodes[nodeIndex], referenceIndex, parentTag); } } else if (typeof n[0] === 'string') { // Element node. const builder: string[] = []; builder.push('<', n[0]); // Never set relative URLs as