embedding things
A reference page, not a piece of writing: it exists so that every kind of embed is proved working rather than promised. Anything below can be copied straight into a new post in _posts/. Delete this file whenever it has stopped being useful — see the README.
Code, with syntax highlighting
Fenced blocks are highlighted server-side, so there is no flash of unstyled code.
// Interval arithmetic: every result carries a bound rather than a hopeful number.
struct Interval {
double lo, hi;
Interval operator*(const Interval& o) const {
const double a = lo * o.lo, b = lo * o.hi;
const double c = hi * o.lo, d = hi * o.hi;
return {std::min({a, b, c, d}), std::max({a, b, c, d})};
}
bool definitely_positive() const { return lo > 0.0; }
};
Inline code works too, and so does maths — \(\varphi = \frac{1+\sqrt5}{2}\) — set with MathJax:
Images
Images go through figure.liquid, which handles responsive sizes, lazy loading and a WebP version for browsers that want one. Add zoomable=true and it opens on click.
An embedded program
Anything that is a self-contained HTML page can be dropped into assets/ and framed in place — a compiled WebAssembly demo, a visualiser, a small game.
Interactive charts
Three chart libraries are wired in. Each is a fenced block of JSON — no JavaScript to write, no build step to run.
Plotly:
{
"data": [
{
"x": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
"y": [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89],
"type": "scatter",
"mode": "lines+markers",
"name": "Fibonacci"
}
],
"layout": { "margin": { "t": 20 }, "yaxis": { "type": "log", "title": "value" }, "xaxis": { "title": "n" } }
}
Chart.js:
{
"type": "bar",
"data": {
"labels": ["2", "4", "8", "16", "32", "64"],
"datasets": [
{
"label": "illustrative tile counts",
"data": [12, 9, 7, 5, 3, 1],
"borderWidth": 1
}
]
},
"options": { "scales": { "y": { "beginAtZero": true } } }
}
Vega-Lite:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "An illustrative scatter of search depth against time.",
"data": {
"values": [
{"depth": 1, "ms": 0.02}, {"depth": 2, "ms": 0.05}, {"depth": 3, "ms": 0.14},
{"depth": 4, "ms": 0.41}, {"depth": 5, "ms": 1.2}, {"depth": 6, "ms": 3.6}
]
},
"mark": {"type": "line", "point": true},
"encoding": {
"x": {"field": "depth", "type": "quantitative", "title": "search depth"},
"y": {"field": "ms", "type": "quantitative", "scale": {"type": "log"}, "title": "milliseconds"}
}
}
The numbers in the last two are placeholders, chosen to make the axes do something.
A Jupyter notebook
Notebooks are converted at build time and rendered inline, code and output together.
Links between pages
Internal links are ordinary paths: projects, apps, contact, and blog, and the PDF at /cv.pdf. The CV page is the one exception — it’s linked by its canonical address, cv, rather than a path on this host.