Skip to content

Commit dce8847

Browse files
authored
esbuild client (#293)
* esbuild client * remove as any * typescript width * esbuild peer dependency
1 parent 5ce3da8 commit dce8847

File tree

5 files changed

+192
-76
lines changed

5 files changed

+192
-76
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@
4545
},
4646
"dependencies": {
4747
"@observablehq/runtime": "^5.9.4",
48-
"@rollup/plugin-terser": "^0.4.4",
4948
"acorn": "^8.11.2",
5049
"acorn-walk": "^8.3.0",
50+
"esbuild": "^0.19.8",
5151
"fast-array-diff": "^1.1.0",
5252
"fast-deep-equal": "^3.1.3",
5353
"gray-matter": "^4.0.3",
@@ -60,6 +60,7 @@
6060
"mime": "^3.0.0",
6161
"open": "^9.1.0",
6262
"rollup": "^4.6.0",
63+
"rollup-plugin-esbuild": "^6.1.0",
6364
"send": "^0.18.0",
6465
"tar-stream": "^3.1.6",
6566
"tsx": "^3.13.0",

src/client/toc.js renamed to src/client/toc.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
const toc = document.querySelector("#observablehq-toc");
1+
const toc = document.querySelector<HTMLElement>("#observablehq-toc");
22
if (toc) {
33
const highlight = toc.appendChild(document.createElement("div"));
44
highlight.classList.add("observablehq-secondary-link-highlight");
5-
const headings = Array.from(document.querySelectorAll(toc.dataset.selector)).reverse();
6-
const links = toc.querySelectorAll(".observablehq-secondary-link");
7-
const relink = () => {
5+
const headings = Array.from(document.querySelectorAll<HTMLElement>(toc.dataset.selector!)).reverse();
6+
const links = toc.querySelectorAll<HTMLElement>(".observablehq-secondary-link");
7+
const relink = (): HTMLElement | undefined => {
88
for (const link of links) {
99
link.classList.remove("observablehq-secondary-link-active");
1010
}
1111
// If there’s a location.hash, highlight that if it’s at the top of the viewport.
1212
if (location.hash) {
1313
for (const heading of headings) {
14-
const hash = heading.querySelector("a[href]")?.hash;
14+
const hash = heading.querySelector<HTMLAnchorElement>("a[href]")?.hash;
1515
if (hash === location.hash) {
1616
const top = heading.getBoundingClientRect().top;
1717
if (0 < top && top < 40) {
1818
for (const link of links) {
19-
if (link.querySelector("a[href]")?.hash === hash) {
19+
if (link.querySelector<HTMLAnchorElement>("a[href]")?.hash === hash) {
2020
link.classList.add("observablehq-secondary-link-active");
2121
return link;
2222
}
@@ -30,9 +30,9 @@ if (toc) {
3030
// Otherwise, highlight the last one that’s above the center of the viewport.
3131
for (const heading of headings) {
3232
if (heading.getBoundingClientRect().top >= innerHeight * 0.5) continue;
33-
const hash = heading.querySelector("a[href]")?.hash;
33+
const hash = heading.querySelector<HTMLAnchorElement>("a[href]")?.hash;
3434
for (const link of links) {
35-
if (link.querySelector("a[href]")?.hash === hash) {
35+
if (link.querySelector<HTMLAnchorElement>("a[href]")?.hash === hash) {
3636
link.classList.add("observablehq-secondary-link-active");
3737
return link;
3838
}
@@ -42,7 +42,7 @@ if (toc) {
4242
};
4343
const intersected = () => {
4444
const link = relink();
45-
highlight.style = link ? `top: ${link.offsetTop}px; height: ${link.offsetHeight}px;` : "";
45+
highlight.style.cssText = link ? `top: ${link.offsetTop}px; height: ${link.offsetHeight}px;` : "";
4646
};
4747
const observer = new IntersectionObserver(intersected, {rootMargin: "0px 0px -50% 0px"});
4848
for (const heading of headings) observer.observe(heading);
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// Override the width definition to use main instead of body (and also use a
22
// ResizeObserver instead of listening for window resize events).
33
export function width({Generators}) {
4-
return Generators.observe((notify) => {
5-
let width;
4+
return Generators.observe((notify: (width: number) => void) => {
5+
let width: number;
66
const observer = new ResizeObserver(([entry]) => {
77
const w = entry.contentRect.width;
88
if (w !== width) notify((width = w));
99
});
10-
observer.observe(document.querySelector("main"));
10+
observer.observe(document.querySelector<HTMLElement>("main")!);
1111
return () => observer.disconnect();
1212
});
1313
}

src/rollup.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {dirname, join, relative} from "node:path";
22
import {cwd} from "node:process";
33
import {fileURLToPath} from "node:url";
4-
import terser from "@rollup/plugin-terser";
54
import {type OutputChunk, rollup} from "rollup";
5+
import esbuild from "rollup-plugin-esbuild";
66

77
export async function rollupClient(clientPath = getClientPath(), {minify = false} = {}): Promise<string> {
88
const bundle = await rollup({
@@ -16,11 +16,12 @@ export async function rollupClient(clientPath = getClientPath(), {minify = false
1616
? {id: `https://cdn.jsdelivr.net/npm/${specifier.slice("npm:".length)}/+esm`}
1717
: null;
1818
}
19-
}
19+
},
20+
esbuild({minify})
2021
]
2122
});
2223
try {
23-
const output = await bundle.generate({format: "es", plugins: minify ? [(terser as any)()] : []});
24+
const output = await bundle.generate({format: "es"});
2425
return output.output.find((o): o is OutputChunk => o.type === "chunk")!.code; // XXX
2526
} finally {
2627
await bundle.close();

0 commit comments

Comments
 (0)