Skip to content

Commit b611a5a

Browse files
authored
feat: view for transform results (#7)
1 parent 1637dfd commit b611a5a

File tree

4 files changed

+105
-11
lines changed

4 files changed

+105
-11
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"repository": "https://github.com/AriPerkkio/vite-plugin-source-map-visualizer",
1818
"scripts": {
1919
"build": "rm -rf ./dist && tsc --project tsconfig.build.json && cp src/*.css dist",
20-
"test": "vitest --coverage",
20+
"test": "vitest --coverage --coverage.include=src",
2121
"typecheck": "tsc --noEmit",
2222
"example": "node scripts/generate-example.mjs",
2323
"deploy": "touch example/.nojekyll && gh-pages --dist example --dotfiles true"

src/plugin.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fs from "node:fs/promises";
22
import { join } from "node:path";
33
import type { Logger, Plugin } from "vite";
4+
import type { TransformResult } from "vite";
45

56
import { toVisualizer } from "./generate-link.js";
67
import { script, style } from "./report.js";
@@ -25,6 +26,8 @@ interface Result {
2526
filename: string;
2627
hash: string;
2728
ssr: boolean;
29+
code: TransformResult["code"];
30+
map: TransformResult["map"];
2831
}
2932

3033
/**
@@ -76,8 +79,9 @@ export function sourcemapVisualizer(options?: Options): Plugin {
7679
const map = this.getCombinedSourcemap();
7780
const hash = toVisualizer({ code, map });
7881
const filename = formatName(id);
82+
const ssr = options?.ssr || false;
7983

80-
results.push({ filename, hash, ssr: options?.ssr || false });
84+
results.push({ filename, hash, code, map, ssr });
8185
},
8286

8387
async buildEnd() {
@@ -116,13 +120,21 @@ function generateHTML(results: Result[]) {
116120
<a href="#">Vite Source Map Visualizer</a>
117121
</h1>
118122
123+
<button id="json-view-toggle" title="View transform results" style="display: none;">
124+
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><g><rect width="24" height="24" opacity="0"/><path d="M15 16H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2z"/><path d="M9 14h3a1 1 0 0 0 0-2H9a1 1 0 0 0 0 2z"/><path d="M19.74 8.33l-5.44-6a1 1 0 0 0-.74-.33h-7A2.53 2.53 0 0 0 4 4.5v15A2.53 2.53 0 0 0 6.56 22h10.88A2.53 2.53 0 0 0 20 19.5V9a1 1 0 0 0-.26-.67zM14 5l2.74 3h-2a.79.79 0 0 1-.74-.85zm3.44 15H6.56a.53.53 0 0 1-.56-.5v-15a.53.53 0 0 1 .56-.5H12v3.15A2.79 2.79 0 0 0 14.71 10H18v9.5a.53.53 0 0 1-.56.5z"/></g></g></svg>
125+
</button>
126+
127+
<button id="visualizer-view-toggle" title="View visualizer" style="display: none;">
128+
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><g><rect width="24" height="24" opacity="0"/><path d="M20.71 19.29l-3.4-3.39A7.92 7.92 0 0 0 19 11a8 8 0 1 0-8 8 7.92 7.92 0 0 0 4.9-1.69l3.39 3.4a1 1 0 0 0 1.42 0 1 1 0 0 0 0-1.42zM5 11a6 6 0 1 1 6 6 6 6 0 0 1-6-6z"/></g></g></svg>
129+
</button>
130+
119131
<button id="menu" title="Toggle file list">
120-
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="menu"><rect width="24" height="24" transform="rotate(180 12 12)" opacity="0"/><rect x="3" y="11" width="18" height="2" rx=".95" ry=".95"/><rect x="3" y="16" width="18" height="2" rx=".95" ry=".95"/><rect x="3" y="6" width="18" height="2" rx=".95" ry=".95"/></g></g></svg>
132+
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><g><rect width="24" height="24" transform="rotate(180 12 12)" opacity="0"/><rect x="3" y="11" width="18" height="2" rx=".95" ry=".95"/><rect x="3" y="16" width="18" height="2" rx=".95" ry=".95"/><rect x="3" y="6" width="18" height="2" rx=".95" ry=".95"/></g></g></svg>
121133
</button>
122134
123135
<button id="theme-toggle" title="Toggle theme">
124-
<svg id="theme-icon-light" class="theme-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="sun"><rect width="24" height="24" transform="rotate(180 12 12)" opacity="0"/><path d="M12 6a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v2a1 1 0 0 0 1 1z"/><path d="M21 11h-2a1 1 0 0 0 0 2h2a1 1 0 0 0 0-2z"/><path d="M6 12a1 1 0 0 0-1-1H3a1 1 0 0 0 0 2h2a1 1 0 0 0 1-1z"/><path d="M6.22 5a1 1 0 0 0-1.39 1.47l1.44 1.39a1 1 0 0 0 .73.28 1 1 0 0 0 .72-.31 1 1 0 0 0 0-1.41z"/><path d="M17 8.14a1 1 0 0 0 .69-.28l1.44-1.39A1 1 0 0 0 17.78 5l-1.44 1.42a1 1 0 0 0 0 1.41 1 1 0 0 0 .66.31z"/><path d="M12 18a1 1 0 0 0-1 1v2a1 1 0 0 0 2 0v-2a1 1 0 0 0-1-1z"/><path d="M17.73 16.14a1 1 0 0 0-1.39 1.44L17.78 19a1 1 0 0 0 .69.28 1 1 0 0 0 .72-.3 1 1 0 0 0 0-1.42z"/><path d="M6.27 16.14l-1.44 1.39a1 1 0 0 0 0 1.42 1 1 0 0 0 .72.3 1 1 0 0 0 .67-.25l1.44-1.39a1 1 0 0 0-1.39-1.44z"/><path d="M12 8a4 4 0 1 0 4 4 4 4 0 0 0-4-4zm0 6a2 2 0 1 1 2-2 2 2 0 0 1-2 2z"/></g></g></svg>
125-
<svg id="theme-icon-dark" class="theme-dark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="moon"><rect width="24" height="24" opacity="0"/><path d="M12.3 22h-.1a10.31 10.31 0 0 1-7.34-3.15 10.46 10.46 0 0 1-.26-14 10.13 10.13 0 0 1 4-2.74 1 1 0 0 1 1.06.22 1 1 0 0 1 .24 1 8.4 8.4 0 0 0 1.94 8.81 8.47 8.47 0 0 0 8.83 1.94 1 1 0 0 1 1.27 1.29A10.16 10.16 0 0 1 19.6 19a10.28 10.28 0 0 1-7.3 3zM7.46 4.92a7.93 7.93 0 0 0-1.37 1.22 8.44 8.44 0 0 0 .2 11.32A8.29 8.29 0 0 0 12.22 20h.08a8.34 8.34 0 0 0 6.78-3.49A10.37 10.37 0 0 1 7.46 4.92z"/></g></g></svg>
136+
<svg id="theme-icon-light" aria-hidden="true" class="theme-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><g><rect width="24" height="24" transform="rotate(180 12 12)" opacity="0"/><path d="M12 6a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v2a1 1 0 0 0 1 1z"/><path d="M21 11h-2a1 1 0 0 0 0 2h2a1 1 0 0 0 0-2z"/><path d="M6 12a1 1 0 0 0-1-1H3a1 1 0 0 0 0 2h2a1 1 0 0 0 1-1z"/><path d="M6.22 5a1 1 0 0 0-1.39 1.47l1.44 1.39a1 1 0 0 0 .73.28 1 1 0 0 0 .72-.31 1 1 0 0 0 0-1.41z"/><path d="M17 8.14a1 1 0 0 0 .69-.28l1.44-1.39A1 1 0 0 0 17.78 5l-1.44 1.42a1 1 0 0 0 0 1.41 1 1 0 0 0 .66.31z"/><path d="M12 18a1 1 0 0 0-1 1v2a1 1 0 0 0 2 0v-2a1 1 0 0 0-1-1z"/><path d="M17.73 16.14a1 1 0 0 0-1.39 1.44L17.78 19a1 1 0 0 0 .69.28 1 1 0 0 0 .72-.3 1 1 0 0 0 0-1.42z"/><path d="M6.27 16.14l-1.44 1.39a1 1 0 0 0 0 1.42 1 1 0 0 0 .72.3 1 1 0 0 0 .67-.25l1.44-1.39a1 1 0 0 0-1.39-1.44z"/><path d="M12 8a4 4 0 1 0 4 4 4 4 0 0 0-4-4zm0 6a2 2 0 1 1 2-2 2 2 0 0 1-2 2z"/></g></g></svg>
137+
<svg id="theme-icon-dark" aria-hidden="true" class="theme-dark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><g><rect width="24" height="24" opacity="0"/><path d="M12.3 22h-.1a10.31 10.31 0 0 1-7.34-3.15 10.46 10.46 0 0 1-.26-14 10.13 10.13 0 0 1 4-2.74 1 1 0 0 1 1.06.22 1 1 0 0 1 .24 1 8.4 8.4 0 0 0 1.94 8.81 8.47 8.47 0 0 0 8.83 1.94 1 1 0 0 1 1.27 1.29A10.16 10.16 0 0 1 19.6 19a10.28 10.28 0 0 1-7.3 3zM7.46 4.92a7.93 7.93 0 0 0-1.37 1.22 8.44 8.44 0 0 0 .2 11.32A8.29 8.29 0 0 0 12.22 20h.08a8.34 8.34 0 0 0 6.78-3.49A10.37 10.37 0 0 1 7.46 4.92z"/></g></g></svg>
126138
</button>
127139
128140
<details id="files" open>
@@ -150,7 +162,7 @@ function generateHTML(results: Result[]) {
150162
</td>
151163
<td class="center">
152164
<a title="Open in source-map-visualization" target="_blank" href="https://evanw.github.io/source-map-visualization#${result.hash}">
153-
<svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="external-link"><rect width="24" height="24" opacity="0"/><path d="M20 11a1 1 0 0 0-1 1v6a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h6a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-6a1 1 0 0 0-1-1z"/><path d="M16 5h1.58l-6.29 6.28a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0L19 6.42V8a1 1 0 0 0 1 1 1 1 0 0 0 1-1V4a1 1 0 0 0-1-1h-4a1 1 0 0 0 0 2z"/></g></g></svg>
165+
<svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><g><rect width="24" height="24" opacity="0"/><path d="M20 11a1 1 0 0 0-1 1v6a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h6a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-6a1 1 0 0 0-1-1z"/><path d="M16 5h1.58l-6.29 6.28a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0L19 6.42V8a1 1 0 0 0 1 1 1 1 0 0 0 1-1V4a1 1 0 0 0-1-1h-4a1 1 0 0 0 0 2z"/></g></g></svg>
154166
</a>
155167
</td>
156168
</tr>
@@ -160,6 +172,7 @@ function generateHTML(results: Result[]) {
160172
161173
</details>
162174
175+
<div id="json-visualizer" style="display: none;"></div>
163176
<iframe id="source-map-visualizer" style="display: none;"></iframe>
164177
</main>
165178
<script>

src/report.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,34 @@ export function script() {
2323
fileList.open = !fileList.open;
2424
});
2525

26+
const jsonView = document.getElementById("json-visualizer")!;
27+
const visualizerView = document.getElementById("source-map-visualizer")!;
28+
const jsonViewToggle = document.querySelector(
29+
"button#json-view-toggle" as "button"
30+
)!;
31+
const visualizerViewToggle = document.querySelector(
32+
"button#visualizer-view-toggle" as "button"
33+
)!;
34+
35+
function setView(view: "json-view" | "visualizer-view") {
36+
if (view === "json-view") {
37+
visualizerView.style.display = "none";
38+
jsonViewToggle.style.display = "none";
39+
visualizerViewToggle.style.display = "block";
40+
jsonView.style.display = "block";
41+
} else {
42+
jsonView.style.display = "none";
43+
visualizerViewToggle.style.display = "none";
44+
visualizerView.style.display = "block";
45+
jsonViewToggle.style.display = "block";
46+
}
47+
}
48+
49+
jsonViewToggle.addEventListener("click", () => setView("json-view"));
50+
visualizerViewToggle.addEventListener("click", () =>
51+
setView("visualizer-view")
52+
);
53+
2654
initializePage();
2755
addEventListener("hashchange", initializePage);
2856

@@ -32,14 +60,49 @@ export function script() {
3260
"iframe#source-map-visualizer" as "iframe"
3361
)!;
3462

63+
Array.from(jsonView.children).map((child) => jsonView.removeChild(child));
64+
3565
if (window.location.hash) {
3666
iframe.src = `https://evanw.github.io/source-map-visualization${window.location.hash}`;
3767
iframe.style.display = "block";
3868
fileList.open = false;
69+
setView("visualizer-view");
70+
71+
const result = convertHash(window.location.hash.slice(1));
72+
const code = document.createElement("pre");
73+
code.textContent = result.code;
74+
jsonView.appendChild(code);
75+
76+
const map = document.createElement("pre");
77+
map.textContent = JSON.stringify(result.map, null, 2);
78+
jsonView.appendChild(map);
3979
} else {
4080
iframe.src = "";
4181
iframe.style.display = "none";
4282
fileList.open = true;
83+
84+
visualizerView.style.display = "none";
85+
visualizerViewToggle.style.display = "none";
86+
jsonView.style.display = "none";
87+
jsonViewToggle.style.display = "none";
88+
}
89+
}
90+
91+
function convertHash(hash: string) {
92+
let bin = atob(hash);
93+
const code = readBuffer();
94+
const map = readBuffer();
95+
96+
return { code, map: JSON.parse(map) };
97+
98+
function readBuffer() {
99+
const zero = bin.indexOf("\0");
100+
const start = zero + 1;
101+
const end = start + (0 | parseInt(bin.slice(0, zero)));
102+
const buffer = decodeURIComponent(bin.slice(start, end));
103+
104+
bin = bin.slice(end);
105+
return buffer;
43106
}
44107
}
45108
}

src/styles.css

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ h1 {
4949
}
5050

5151
button#theme-toggle,
52-
button#menu {
52+
button#menu,
53+
button#json-view-toggle,
54+
button#visualizer-view-toggle {
5355
width: 3rem;
5456
height: 3rem;
5557
border: 0;
@@ -63,18 +65,23 @@ button#menu {
6365
}
6466

6567
button#theme-toggle {
66-
right: 1rem;
68+
right: 2rem;
6769
}
6870

6971
button#menu {
70-
right: 5rem;
72+
right: 6rem;
73+
}
74+
75+
button#json-view-toggle,
76+
button#visualizer-view-toggle {
77+
right: 10rem;
7178
}
7279

7380
a {
7481
color: var(--text-accent);
7582
}
7683

77-
details#files {
84+
details#files[open] {
7885
margin: 2rem;
7986
}
8087

@@ -105,5 +112,16 @@ svg.icon {
105112

106113
iframe {
107114
height: 100%;
108-
margin: 1rem;
115+
margin: 2rem;
116+
}
117+
118+
#json-visualizer {
119+
margin: 2rem;
120+
}
121+
122+
#json-visualizer pre {
123+
overflow: auto;
124+
border: 0.1rem solid var(--border);
125+
margin-bottom: 2rem;
126+
padding: 2rem;
109127
}

0 commit comments

Comments
 (0)