From e8261ed040cd3447dc770643842258240d92aabe Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 9 Jul 2026 05:17:37 +0200 Subject: [PATCH] Add docs/ site + Pages Actions deploy; drop version suffix from release assets - docs/ contains the source for github.io: /xkcd-script/ (font preview, ported from the old root preview.html) and /mathjax/ (MathJax integration demo). Shared site.css + site.js provide the common header and querystring-backed share URL. - docs/build.sh assembles build/html/ by copying docs/ and pulling the current release's xkcd-script.{otf,ttf,woff,woff2} + xkcd-mathjax3.js into build/html/assets/. Used both locally and by the workflow. - .github/workflows/pages.yml runs the same script and deploys via actions/deploy-pages, triggered on push to master (docs/**), on release published, or manually. - Release artifacts now use unversioned filenames (version stays in the font name table and JS header). Enables /releases/latest/download/... stable URLs and simplifies docs asset naming. - Root preview.html removed; docs/preview.html redirects to /xkcd-script/ preserving querystring + hash. --- .github/workflows/pages.yml | 49 ++++ .github/workflows/release.yml | 11 +- .gitignore | 1 + docs/_config.yml | 0 docs/build.sh | 35 +++ docs/mathjax/index.html | 218 +++++++++++++++ docs/preview.html | 11 + docs/site.css | 60 ++++ docs/site.js | 86 ++++++ docs/xkcd-script/index.html | 120 ++++++++ preview.html | 256 ------------------ .../generator/generate_release_artifacts.py | 11 +- 12 files changed, 590 insertions(+), 268 deletions(-) create mode 100644 .github/workflows/pages.yml create mode 100644 docs/_config.yml create mode 100755 docs/build.sh create mode 100644 docs/mathjax/index.html create mode 100644 docs/preview.html create mode 100644 docs/site.css create mode 100644 docs/site.js create mode 100644 docs/xkcd-script/index.html delete mode 100644 preview.html diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..4ab1d18 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,49 @@ +name: Deploy docs to GitHub Pages + +on: + push: + branches: [master] + paths: + - 'docs/**' + - '.github/workflows/pages.yml' + release: + types: [published] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/checkout@v4 + + - name: Assemble site + env: + REPO: ${{ github.repository }} + run: ./docs/build.sh + + - uses: actions/configure-pages@v5 + + - uses: actions/upload-pages-artifact@v3 + with: + path: build/html + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 39e7839..ff8c688 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,12 +31,11 @@ jobs: - name: Upload assets to the release env: TAG: ${{ github.event.release.tag_name }} - VERSION: ${{ steps.version.outputs.value }} run: | gh release upload "$TAG" \ - "dist/xkcd-script-${VERSION}.otf" \ - "dist/xkcd-script-${VERSION}.ttf" \ - "dist/xkcd-script-${VERSION}.woff" \ - "dist/xkcd-script-${VERSION}.woff2" \ - "dist/xkcd-mathjax3-${VERSION}.js" \ + "dist/xkcd-script.otf" \ + "dist/xkcd-script.ttf" \ + "dist/xkcd-script.woff" \ + "dist/xkcd-script.woff2" \ + "dist/xkcd-mathjax3.js" \ --clobber diff --git a/.gitignore b/.gitignore index cebfb27..613cf23 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .DS_store .font-cache xkcd-script/generated +/build *.afm fonts.conf diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..e69de29 diff --git a/docs/build.sh b/docs/build.sh new file mode 100755 index 0000000..bd5e8a8 --- /dev/null +++ b/docs/build.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Assemble the Pages site: docs/ + release assets → $OUT +# +# Env vars: +# OUT output directory, relative to repo root (default: _site) +# TAG release tag to pull assets from (default: latest) +# REPO GitHub repo (default: ipython/xkcd-font) +set -euo pipefail + +OUT="${OUT:-build/html}" +TAG="${TAG:-}" +REPO="${REPO:-ipython/xkcd-font}" + +DOCS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT="$(cd "$DOCS/.." && pwd)" +DEST="$ROOT/$OUT" + +rm -rf "$DEST" +mkdir -p "$DEST/assets" +# Copy every doc source except this build script itself. +rsync -a --exclude='build.sh' "$DOCS/" "$DEST/" + +download=(gh release download + --repo "$REPO" + --dir "$DEST/assets" + --pattern xkcd-script.otf + --pattern xkcd-script.ttf + --pattern xkcd-script.woff + --pattern xkcd-script.woff2 + --pattern xkcd-mathjax3.js) +[ -n "$TAG" ] && download+=("$TAG") + +"${download[@]}" + +echo "Site assembled at $DEST" diff --git a/docs/mathjax/index.html b/docs/mathjax/index.html new file mode 100644 index 0000000..1842224 --- /dev/null +++ b/docs/mathjax/index.html @@ -0,0 +1,218 @@ + + + + +xkcd-script + MathJax + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + +

Large operators: inline vs display

+ +

Inline: $\sum_{k=1}^{n} k$ and $\int_0^1 x^2\,dx$ and $\prod_{k=1}^{n} k$

+ +

Display: +$$\sum_{k=1}^{n} k = \frac{n(n+1)}{2}$$ +$$\int_0^\infty e^{-x}\,dx = 1 \qquad \int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}$$ +$$\prod_{p\;\text{prime}} \frac{1}{1-p^{-s}} = \sum_{n=1}^{\infty} \frac{1}{n^s}$$ +

+ +

Algebra

+ +

Quadratic formula: +$$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$

+ +

Pythagorean theorem: $a^2 + b^2 = c^2$

+ +

Binomial theorem: +$$\sum_{k=0}^{n} \binom{n}{k} x^k y^{n-k} = (x + y)^n$$

+ +

Calculus

+ +

Definition of derivative: +$$f'(x) = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}$$

+ +

Gaussian integral: +$$\int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}$$

+ +

Product rule: $\dfrac{d}{dx}\bigl[f(x)\,g(x)\bigr] = f'(x)\,g(x) + f(x)\,g'(x)$

+ +

Greek letters

+ +

Euler's identity: $e^{i\pi} + 1 = 0$

+ +

$\alpha,\ \beta,\ \gamma,\ \delta,\ \varepsilon,\ \zeta,\ \eta,\ + \theta,\ \iota,\ \kappa,\ \lambda,\ \mu,\ \nu,\ \xi,\ \pi,\ + \rho,\ \sigma,\ \tau,\ \upsilon,\ \phi,\ \chi,\ \psi,\ \omega$

+ +

Fourier transform: +$$\hat{f}(\xi) = \int_{-\infty}^{\infty} f(x)\,e^{-2\pi i x \xi}\,dx$$

+ +

Physics

+ +

Einstein: $E = mc^2$

+ +

Schrödinger equation: +$$i\hbar\frac{\partial\psi}{\partial t} = \hat{H}\psi$$

+ +

Maxwell in free space: +$$\nabla \cdot \mathbf{E} = 0 \qquad \nabla \times \mathbf{E} = -\frac{\partial \mathbf{B}}{\partial t}$$

+ +

Piecewise definitions (stretchy {)

+ +

Two rows (short brace): +$$|x| = \begin{cases} x, & \text{if } x \geq 0 \\ -x, & \text{if } x < 0 \end{cases}$$

+ +

Four rows (tall brace): +$$f(x) = \begin{cases} + \dfrac{\sin x}{x}, & \text{if } x > 0 \\[6pt] + \displaystyle\sum_{k=0}^{\infty} \frac{(-1)^k x^{2k}}{(2k+1)!}, & \text{if } x = 0 \\[6pt] + -\sqrt{|x|}, & \text{if } -1 \leq x < 0 \\[4pt] + \infty, & \text{otherwise} +\end{cases}$$

+ +

Stretchy delimiters

+ +

Two-high (\binom): +$$\binom{n}{k}$$

+ +

Around a fraction: +$$\left( \dfrac{\frac{a}{b}}{\frac{c}{d}} \right)^{n} \qquad + \left[ \dfrac{\frac{a}{b}}{\frac{c}{d}} \right]^{n}$$

+ +

3×3 matrix: +$$\begin{pmatrix} + a_{11} & a_{12} & a_{13} \\ + a_{21} & a_{22} & a_{23} \\ + a_{31} & a_{32} & a_{33} +\end{pmatrix} \qquad +\begin{bmatrix} + a_{11} & a_{12} & a_{13} \\ + a_{21} & a_{22} & a_{23} \\ + a_{31} & a_{32} & a_{33} +\end{bmatrix}$$

+ +

Stretchy arrows

+ +

Vector accents: $\vec{v},\ \vec{F},\ \vec{p},\ \vec{\mathbf{0}},\ \vec{\mathbf{B}},\ \vec{ABC},\ \overrightarrow{ABC},\ \overleftarrow{ABC}$

+ +

Stretchy operators with labels: +$A \xrightarrow{f} B \xrightarrow{n+\mu-1} C \qquad X \xleftarrow{g} Y$

+ +

AMScd commutative diagram: +$$\begin{CD} A @>f>> B \\ @VgVV @VVhV \\ C @>>k> D \end{CD}$$

+ +
+ + diff --git a/docs/preview.html b/docs/preview.html new file mode 100644 index 0000000..f5600f7 --- /dev/null +++ b/docs/preview.html @@ -0,0 +1,11 @@ + + + + +xkcd-font + + + +

Moved to ./xkcd-script/.

+ + diff --git a/docs/site.css b/docs/site.css new file mode 100644 index 0000000..21e1133 --- /dev/null +++ b/docs/site.css @@ -0,0 +1,60 @@ +@font-face { + font-family: xkcd-script; + src: url('assets/xkcd-script.woff2') format('woff2'), + url('assets/xkcd-script.woff') format('woff'); +} + +body { + margin: 0; + background: #fff; +} + +.xkcd-script { + font-family: xkcd-script; + color: black; + line-height: 150%; +} + +.site-header { + background-color: #96A8C8; + padding: 15px 15px 1em 15px; + overflow: hidden; +} +.site-header h1 { + font-family: xkcd-script; + margin: 0; + font-size: 2em; + font-weight: bold; +} +.site-header .summary { + font-family: xkcd-script; + font-size: 1.5em; + max-width: calc(100% - 150px); + margin: 0; +} +.site-header .nav-links { + font-family: xkcd-script; + font-size: 1em; + margin: 0.3em 0 0 0; +} +.site-header a { + color: #003366; +} + +.share-row { + padding: 1em 15px; + display: flex; + align-items: center; + gap: 0.5em; +} +.share-row label { + font-weight: bold; + min-width: 6em; +} +.share-row input { + flex: 1; + padding: 0.4em 0.6em; + border: 1px solid #999; + background: #fff; + font-size: 0.9em; +} diff --git a/docs/site.js b/docs/site.js new file mode 100644 index 0000000..2f39770 --- /dev/null +++ b/docs/site.js @@ -0,0 +1,86 @@ +// Shared query-string + share-URL helpers for xkcd-font docs. +// +// Public API on window.XkcdSite: +// getParams() → object of decoded query-string params (recomputed each call) +// setParam(key, value) → push key=value into ?query and update the share-URL input. +// value may be null/undefined to remove the key. +// bindTextarea(el, key) → mirror el's value to ?=… on every input event; on load +// and popstate, restore el's value from that param if present. +// Fires a synthetic 'input' event after restoring so callers' +// own listeners can react. +// onShareUrlReady(cb) → cb() runs once the share-URL input is populated. + +(function () { + 'use strict'; + + function getParams() { + var out = {}; + var q = window.location.search.replace(/^\?/, ''); + if (!q) return out; + q.split('&').forEach(function (kv) { + var eq = kv.indexOf('='); + var k = decodeURIComponent((eq < 0 ? kv : kv.slice(0, eq)).replace(/\+/g, ' ')); + var v = eq < 0 ? '' : decodeURIComponent(kv.slice(eq + 1).replace(/\+/g, ' ')); + out[k] = v; + }); + return out; + } + + function buildQuery(params) { + var parts = []; + Object.keys(params).forEach(function (k) { + var v = params[k]; + if (v === undefined || v === null) return; + parts.push(encodeURIComponent(k) + '=' + encodeURIComponent(v)); + }); + return parts.length ? '?' + parts.join('&') : ''; + } + + function updateShareInput() { + var input = document.getElementById('share-url-input'); + if (input) input.value = window.location.href; + } + + function setParam(key, value) { + var params = getParams(); + if (value === undefined || value === null) delete params[key]; + else params[key] = value; + var url = window.location.pathname + buildQuery(params) + window.location.hash; + history.replaceState({}, '', url); + updateShareInput(); + } + + function bindTextarea(el, key) { + function restore() { + var params = getParams(); + if (Object.prototype.hasOwnProperty.call(params, key)) { + el.value = params[key]; + el.dispatchEvent(new Event('input', {bubbles: true})); + } + } + restore(); + window.addEventListener('popstate', restore); + el.addEventListener('input', function () { + setParam(key, el.value); + }); + } + + function onShareUrlReady(cb) { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', function () { + updateShareInput(); + cb && cb(); + }); + } else { + updateShareInput(); + cb && cb(); + } + } + + window.XkcdSite = { + getParams: getParams, + setParam: setParam, + bindTextarea: bindTextarea, + onShareUrlReady: onShareUrlReady, + }; +})(); diff --git a/docs/xkcd-script/index.html b/docs/xkcd-script/index.html new file mode 100644 index 0000000..ad53fe3 --- /dev/null +++ b/docs/xkcd-script/index.html @@ -0,0 +1,120 @@ + + + + +xkcd-font preview + + + + + + + +
+ +
+ + + + + + + + + diff --git a/preview.html b/preview.html deleted file mode 100644 index 28f6d6b..0000000 --- a/preview.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - - - - - - - -
-
-
-

The xkcd font

-

brought to you by the ipython/xkcd-font team

-
-
- -
- -
-
- - - - - diff --git a/xkcd-script/generator/generate_release_artifacts.py b/xkcd-script/generator/generate_release_artifacts.py index 5393e68..fc963fa 100644 --- a/xkcd-script/generator/generate_release_artifacts.py +++ b/xkcd-script/generator/generate_release_artifacts.py @@ -168,13 +168,12 @@ def main(argv: list[str] | None = None) -> int: validate_version(args.version) args.out_dir.mkdir(parents=True, exist_ok=True) - stem = f"xkcd-script-{args.version}" otf_in = args.font_dir / "xkcd-script.otf" ttf_in = args.font_dir / "xkcd-script.ttf" - otf_out = args.out_dir / f"{stem}.otf" - ttf_out = args.out_dir / f"{stem}.ttf" - woff_out = args.out_dir / f"{stem}.woff" - woff2_out = args.out_dir / f"{stem}.woff2" + otf_out = args.out_dir / "xkcd-script.otf" + ttf_out = args.out_dir / "xkcd-script.ttf" + woff_out = args.out_dir / "xkcd-script.woff" + woff2_out = args.out_dir / "xkcd-script.woff2" if not otf_in.exists(): raise FileNotFoundError(otf_in) @@ -191,7 +190,7 @@ def main(argv: list[str] | None = None) -> int: regenerate_woff2(otf_out, woff2_out) js_source = args.js.read_text(encoding="utf-8") - js_out = args.out_dir / f"xkcd-mathjax3-{args.version}.js" + js_out = args.out_dir / "xkcd-mathjax3.js" js_out.write_text( inject_js_version(js_source, version=args.version, build_date=args.build_date), encoding="utf-8",