Skip to content

Commit 7fa6814

Browse files
committed
feat: Add @observablehq/notebook-kit support
Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
1 parent 9248954 commit 7fa6814

16 files changed

Lines changed: 2845 additions & 1178 deletions

package-lock.json

Lines changed: 2140 additions & 1152 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/observablehq-compiler/.vscode/launch.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@
4343
"!**/node_modules/**"
4444
]
4545
},
46+
{
47+
"name": "index-kit.html",
48+
"request": "launch",
49+
"type": "msedge",
50+
"url": "http://localhost:5514/index-kit.html",
51+
"runtimeArgs": [
52+
"--disable-web-security"
53+
],
54+
"webRoot": "${workspaceFolder}",
55+
"outFiles": [
56+
"${workspaceFolder}/**/*.js",
57+
"!**/node_modules/**"
58+
]
59+
},
4660
{
4761
"name": "index-preview.html",
4862
"request": "launch",
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { neutralTpl } from "@hpcc-js/esbuild-plugins";
1+
import { nodeBoth } from "@hpcc-js/esbuild-plugins";
22

33
// config ---
4-
await neutralTpl("src/index.ts", "dist/index");
4+
await Promise.all([
5+
nodeBoth("src/index.node.ts", "dist/node/index")
6+
]);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<title>Home</title>
6+
<style>
7+
body {
8+
font-family: Arial, sans-serif;
9+
margin: 0;
10+
padding: 0;
11+
background-color: #f0f0f0;
12+
}
13+
14+
h1 {
15+
text-align: center;
16+
margin-top: 50px;
17+
}
18+
19+
.placeholder {
20+
width: 100%;
21+
height: 500px;
22+
background-color: #fff;
23+
margin-top: 20px;
24+
}
25+
</style>
26+
</head>
27+
28+
<body>
29+
<h1>ESM Quick Test</h1>
30+
<div class="placeholder" id="placeholder-kit"></div>
31+
<script type="module">
32+
import { testHtml } from "./tests/index-notebookkit.ts";
33+
testHtml("placeholder-kit");
34+
</script>
35+
<hr>
36+
<div class="placeholder" id="placeholder-ojs"></div>
37+
<script type="module">
38+
import { testOjs } from "./tests/index-notebookkit.ts";
39+
testOjs("placeholder-ojs");
40+
</script>
41+
<hr>
42+
<div class="placeholder" id="placeholder-omd"></div>
43+
<script type="module">
44+
import { testOmd } from "./tests/index-notebookkit.ts";
45+
testOmd("placeholder-omd");
46+
</script>
47+
48+
</body>
49+
50+
</html>

packages/observablehq-compiler/package.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
},
2626
"scripts": {
2727
"clean": "rimraf --glob lib* types dist *.tsbuildinfo .turbo",
28-
"bundle": "vite build",
28+
"bundle-node": "node ./esbuild.js",
29+
"bundle-browser": "vite build",
30+
"bundle": "run-s bundle-browser bundle-node",
2931
"bundle-watch": "vite --port 5514",
3032
"gen-types": "tsc --project tsconfig.json",
3133
"gen-types-watch": "npm run gen-types -- --watch",
@@ -43,12 +45,16 @@
4345
"update-major": "npx --yes npm-check-updates -u"
4446
},
4547
"dependencies": {
48+
"jsdom": "26.1.0",
4649
"yargs": "17.7.2"
4750
},
4851
"devDependencies": {
4952
"@hpcc-js/esbuild-plugins": "^1.4.9",
53+
"@observablehq/notebook-kit": "1.0.1",
5054
"@observablehq/parser": "6.1.0",
51-
"@observablehq/runtime": "5.9.9"
55+
"@observablehq/runtime": "5.9.9",
56+
"@types/jsdom": "21.1.7",
57+
"vite-plugin-top-level-await": "^1.6.0"
5258
},
5359
"repository": {
5460
"type": "git",
@@ -69,4 +75,4 @@
6975
"url": "https://github.com/hpcc-systems/Visualization/issues"
7076
},
7177
"homepage": "https://github.com/hpcc-systems/Visualization/tree/trunk/packages/observablehq-compiler"
72-
}
78+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<!doctype html>
2+
<notebook theme="air">
3+
<title>Brushable scatterplot</title>
4+
<script id="1" type="text/markdown">
5+
<div style="color: grey; font: 13px/25.5px var(--sans-serif); text-transform: uppercase;"><h1 style="display: none;">Brushable scatterplot</h1><a href="https://d3js.org/">D3</a><a href="/@d3/gallery">Gallery</a></div>
6+
7+
# Brushable scatterplot
8+
9+
This chart shows the inverse relationship between engine power (*y*-axis) and fuel efficiency (*x*-axis) in ${data.length} cars from 1970–1982. Brushing this scatterplot will show the selected data points.
10+
</script>
11+
<script id="10" type="application/vnd.observable.javascript" pinned="">
12+
viewof selection = {
13+
14+
// Specify the chart’s dimensions.
15+
const width = 928;
16+
const height = 600;
17+
const marginTop = 20;
18+
const marginRight = 30;
19+
const marginBottom = 30;
20+
const marginLeft = 40;
21+
22+
// Create the horizontal (x) scale, positioning N/A values on the left margin.
23+
const x = d3.scaleLinear()
24+
.domain([0, d3.max(data, d => d["Miles_per_Gallon"])]).nice()
25+
.range([marginLeft, width - marginRight])
26+
.unknown(marginLeft);
27+
28+
// Create the vertical (y) scale, positioning N/A values on the bottom margin.
29+
const y = d3.scaleLinear()
30+
.domain([0, d3.max(data, d => d["Horsepower"])]).nice()
31+
.range([height - marginBottom, marginTop])
32+
.unknown(height - marginBottom);
33+
34+
// Create the SVG container.
35+
const svg = d3.create("svg")
36+
.attr("viewBox", [0, 0, width, height])
37+
.property("value", []);
38+
39+
// Append the axes.
40+
svg.append("g")
41+
.attr("transform", `translate(0,${height - marginBottom})`)
42+
.call(d3.axisBottom(x))
43+
.call(g => g.select(".domain").remove())
44+
.call(g => g.append("text")
45+
.attr("x", width - marginRight)
46+
.attr("y", -4)
47+
.attr("fill", "#000")
48+
.attr("font-weight", "bold")
49+
.attr("text-anchor", "end")
50+
.text("Miles per Gallon"));
51+
52+
svg.append("g")
53+
.attr("transform", `translate(${marginLeft},0)`)
54+
.call(d3.axisLeft(y))
55+
.call(g => g.select(".domain").remove())
56+
.call(g => g.select(".tick:last-of-type text").clone()
57+
.attr("x", 4)
58+
.attr("text-anchor", "start")
59+
.attr("font-weight", "bold")
60+
.text("Horsepower"));
61+
62+
// Append the dots.
63+
const dot = svg.append("g")
64+
.attr("fill", "none")
65+
.attr("stroke", "steelblue")
66+
.attr("stroke-width", 1.5)
67+
.selectAll("circle")
68+
.data(data)
69+
.join("circle")
70+
.attr("transform", d => `translate(${x(d["Miles_per_Gallon"])},${y(d["Horsepower"])})`)
71+
.attr("r", 3);
72+
73+
// Create the brush behavior.
74+
svg.call(d3.brush().on("start brush end", ({selection}) => {
75+
let value = [];
76+
if (selection) {
77+
const [[x0, y0], [x1, y1]] = selection;
78+
value = dot
79+
.style("stroke", "gray")
80+
.filter(d => x0 <= x(d["Miles_per_Gallon"]) && x(d["Miles_per_Gallon"]) < x1
81+
&& y0 <= y(d["Horsepower"]) && y(d["Horsepower"]) < y1)
82+
.style("stroke", "steelblue")
83+
.data();
84+
} else {
85+
dot.style("stroke", "steelblue");
86+
}
87+
88+
// Inform downstream cells that the selection has changed.
89+
svg.property("value", value).dispatch("input");
90+
}));
91+
92+
return svg.node();
93+
}
94+
</script>
95+
<script id="65" type="application/vnd.observable.javascript" pinned="">
96+
selection
97+
</script>
98+
<script id="3" type="application/vnd.observable.javascript" pinned="">
99+
data = FileAttachment("cars-2.csv").csv({typed: true})
100+
</script>
101+
<script id="281" type="text/markdown">
102+
Thanks to [John Alexis Guerra Gómez](/@john-guerra) for suggestions.
103+
</script>
104+
</notebook>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<notebook theme="air">
3+
<title>Five-Minute Introduction</title>
4+
<script id="1" type="text/markdown">
5+
# Five-Minute Introduction
6+
7+
Welcome! This notebook gives a quick overview of Observable. For a more technical introduction, see [Observable’s not JavaScript](/@observablehq/observables-not-javascript). For hands-on, see our [introductory tutorial series](/collection/@observablehq/introduction). To watch rather than read, see our [short introductory video](https://www.youtube.com/watch?v=uEmDwflQ3xE)!
8+
9+
An Observable notebook consists of cells. Each cell is a snippet of JavaScript. You can see (and edit!) the code for any cell by clicking the menu <svg viewBox="0 0 8 14" fill="currentColor" stroke="none" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" width="8" height="14"><circle r="1.5" cx="4" cy="2"></circle><circle r="1.5" cx="4" cy="7"></circle><circle r="1.5" cx="4" cy="12"></circle></svg> in the left margin.
10+
</script>
11+
<script id="5" type="module" pinned="">
12+
display(2 * 3 * 7)
13+
</script>
14+
</notebook>
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export const PKG_NAME = "@hpcc-js/observablehq-compiler";
2-
export const PKG_VERSION = "3.2.0";
3-
export const BUILD_VERSION = "3.2.1";
2+
export const PKG_VERSION = "3.3.9";
3+
export const BUILD_VERSION = "3.9.1";
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { JSDOM } from "jsdom";
2+
3+
const { window } = new JSDOM();
4+
globalThis.document = window.document;
5+
globalThis.DOMParser = window.DOMParser;
6+
7+
export * from "./index.ts";
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
export type { ohq } from "./observable-shim.ts";
22

33
export * from "./compiler.ts";
4-
export { ojs2notebook, omd2notebook, download } from "./util.ts";
4+
export { ojs2notebook, omd2notebook, omd2notebookKit, ojs2notebookKit, download } from "./util.ts";
55
export * from "./writer.ts";
66

7+
export * from "./kit/index.ts";
8+
79
import "../src/index.css";

0 commit comments

Comments
 (0)