Sure! Hereās an example that builds a chart with Plot (in āserver-side renderingā mode, using linkedom instead of the browser DOM).
First, add the necessary packages to your project:
yarn add d3 @observablehq/plot linkedom
Then create the file:
import * as Plot from "@observablehq/plot";
import * as d3 from "d3";
import {parseHTML} from "linkedom";
const barley = await d3.csv(
"https://raw.githubusercontent.com/observablehq/plot/main/test/data/barley.csv",
d3.autoType
);
function beckerBarley() {
const {document} = parseHTML("<a>");
const chart = Plot.plot({
document,
marginLeft: 110,
height: 800,
grid: true,
x: {nice: true},
y: {inset: 5},
color: {type: "categorical"},
facet: {marginRight: 90},
marks: [
Plot.frame(),
Plot.dot(barley, {
x: "yield",
y: "variety",
fy: "site",
stroke: "year",
sort: {fy: "x", y: "x", reduce: "median", reverse: true}
})
]
});
return `${chart}`.replace(
/^<svg /,
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" '
);
}
process.stdout.write(beckerBarley());
This data loader is written in JavaScript and emits svg, it needs a double extension .svg.js (save it under becker.svg.js
).
In a page named becker.md
, call it like this:
```js
display(await FileAttachment("becker.svg").image());
```
You should then see:
To output png instead of svg, you need a supplementary step. Weāre going to use resvg:
yarn add @resvg/resvg-j
The data loader must be adapted a little:
import * as Plot from "@observablehq/plot";
import * as d3 from "d3";
import {parseHTML} from "linkedom";
import {Resvg} from "@resvg/resvg-js";
const barley = await d3.csv(
"https://raw.githubusercontent.com/observablehq/plot/main/test/data/barley.csv",
d3.autoType
);
function beckerBarley() {
const {document} = parseHTML("<a>");
const chart = Plot.plot({
document,
marginLeft: 110,
height: 800,
grid: true,
x: {nice: true},
y: {inset: 5},
color: {type: "categorical"},
facet: {marginRight: 90},
marks: [
Plot.frame(),
Plot.dot(barley, {
x: "yield",
y: "variety",
fy: "site",
stroke: "year",
sort: {fy: "x", y: "x", reduce: "median", reverse: true}
})
]
});
chart.setAttribute("xmlns", "http://www.w3.org/2000/svg");
return new Resvg(chart.outerHTML, {
fitTo: {
mode: "width",
value: 2 * chart.getAttribute("width")
}
})
.render()
.asPng();
}
process.stdout.write(beckerBarley());
Save this as becker.png.js
then use:
```js
display(await FileAttachment("becker.png").image({style: "max-width: 100%;"}));
```
I understand that this is a lot of code, and weāll want to make helper functions to make this easier. Butā¦ it works!