From d1598c8cc7daaf6bebe0a651964fd18085174fec Mon Sep 17 00:00:00 2001 From: tannevaled Date: Tue, 20 Oct 2026 21:31:12 +0200 Subject: [PATCH] Add the go-scikit documentation site Hugo with the tannevaled/hextra fork pinned at v0.16.0 and the go-scikit brand as submodules, built and published like go-numerics/docs (versioned builds on gh-pages), without the figures job. A page per parity-plan organisation with the status of its packages, and a table of the established organisations with their landing and docs links. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/docs.yml | 230 +++++++++++++++++++ .gitignore | 8 + .gitmodules | 6 + README.md | 26 ++- assets/css/custom.css | 35 +++ branding | 1 + content/en/_index.md | 53 +++++ content/en/approx.md | 27 +++ content/en/bignum.md | 24 ++ content/en/dsp.md | 18 ++ content/en/sparse.md | 23 ++ hugo.yaml | 161 +++++++++++++ i18n/en.yaml | 5 + layouts/_partials/custom/content-begin.html | 30 +++ layouts/_partials/custom/version-select.html | 118 ++++++++++ layouts/_partials/favicons.html | 8 + renovate.json | 4 + scripts/publish-version.sh | 87 +++++++ themes/hextra | 1 + 19 files changed, 863 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 assets/css/custom.css create mode 160000 branding create mode 100644 content/en/_index.md create mode 100644 content/en/approx.md create mode 100644 content/en/bignum.md create mode 100644 content/en/dsp.md create mode 100644 content/en/sparse.md create mode 100644 hugo.yaml create mode 100644 i18n/en.yaml create mode 100644 layouts/_partials/custom/content-begin.html create mode 100644 layouts/_partials/custom/version-select.html create mode 100644 layouts/_partials/favicons.html create mode 100644 renovate.json create mode 100755 scripts/publish-version.sh create mode 160000 themes/hextra diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..1678c57 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,230 @@ +name: docs + +# Every documentation version is a separate Hugo build, published under +# https://go-scikit.github.io/docs// on the gh-pages branch, where +# is the newest minor version among the libraries the pages describe +# (params.libraries in hugo.yaml: v0.1.2 -> 0.1), or "main" while none of +# them is tagged. main is that version's source: each push to main replaces /docs//, and +# /docs/latest/ follows the newest. Pull requests build and check, and publish +# nothing. + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +# The build needs nothing beyond the source. Write access to the repository +# is granted to the deploy job alone, below, so a pull request build cannot +# push to gh-pages. +permissions: + contents: read + +env: + HUGO_VERSION: "0.167.0" + # sha256 of hugo_${HUGO_VERSION}_linux-amd64.tar.gz, from the release's checksums.txt. + HUGO_SHA256: "4d84519b9f619e6d4c3fb45a50157abeabeb724f859c60605f44c23def6e1169" + DOCS_URL: "https://go-scikit.github.io/docs" + +jobs: + build: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + # themes/hextra (the tannevaled/hextra fork, pinned to a release tag) + # and branding (go-scikit/brand) are submodules. + submodules: recursive + # The whole history: each page's creation and modification come from git. + fetch-depth: 0 + + - name: Install Hugo ${{ env.HUGO_VERSION }} + run: | + curl -fsSL -o /tmp/hugo.tar.gz \ + "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/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-amd64.tar.gz" + echo "${HUGO_SHA256} /tmp/hugo.tar.gz" | sha256sum -c - + sudo tar -xzf /tmp/hugo.tar.gz -C /usr/local/bin hugo + hugo version + + # The version label is the newest minor version among the libraries + # params.libraries in hugo.yaml names ("main" until one is released), and + # it is the last segment of baseURL: the version selector reads it there. + - name: Version + id: version + run: | + set -euo pipefail + libs=$(hugo config --format json | jq -r '.params.libraries | to_entries[] | "\(.key) \(.value)"') + test -n "${libs}" || { echo "::error::params.libraries in hugo.yaml is empty"; exit 1; } + minors="" + while read -r name tag; do + if [ "${tag}" = main ]; then continue; fi + minor=$(printf '%s\n' "${tag}" | sed -nE 's/^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/\1.\2/p') + if [ -z "${minor}" ]; then + echo "::error::params.libraries.${name} in hugo.yaml is \"${tag}\", not vMAJOR.MINOR.PATCH or main" + exit 1 + fi + minors=$(printf '%s\n%s\n' "${minors}" "${minor}") + done <<< "${libs}" + version=$(printf '%s\n' "${minors}" | sed '/^$/d' | sort -t. -k1,1nr -k2,2nr | sed -n 1p) + version=${version:-main} + echo "version=${version}" >> "$GITHUB_OUTPUT" + echo "libraries: $(echo ${libs}); documentation version ${version}" + + # Each page's creation (first commit, followed across renames) and its + # author, for the page history at its foot (params.page.history). + - name: Page history + run: | + mkdir -p data + sh themes/hextra/scripts/page-history.sh > data/pagehistory.json + + # --panicOnWarning: a deprecated setting or a template warning fails the + # build rather than scrolling by. A broken {{< relref >}} is an error. + - name: Build + env: + HUGO_ENVIRONMENT: production + run: >- + hugo --gc --minify --panicOnWarning --printPathWarnings + --baseURL "${DOCS_URL}/${{ steps.version.outputs.version }}/" + + # Internal links and anchors, offline, with the site laid out under + # /docs// as it is served. + - name: Lay out the site for the link check + run: | + mkdir -p _check/docs + cp -R public "_check/docs/${{ steps.version.outputs.version }}" + + - name: Check links + uses: lycheeverse/lychee-action@v2 + with: + args: >- + --offline --no-progress --include-fragments + --index-files index.html + --root-dir ${{ github.workspace }}/_check + '_check/docs/**/*.html' + fail: true + + - uses: actions/upload-artifact@v7 + with: + name: site + path: public + retention-days: 7 + + # The offline check above proves the site's own links and anchors. An + # https:// URL is text to it: this job fetches each one the pages name. + links: + name: every external link resolves + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Check + run: | + set -uo pipefail + # The character class matters: an extractor stopping only at ) and " + # carries a closing > or < into the request. + urls=$(grep -rhoE 'https?://[^)">< [:space:]]+' content/ README.md | sed -E 's/[.,`]+$//' | sort -u) + test -n "$urls" || { echo "::error::no links found; are the pages still there?"; exit 1; } + echo "checking $(printf '%s\n' "$urls" | wc -l) distinct URLs" + fail=0 + while read -r u; do + case "$u" in + # Renders whatever it is asked for; proves nothing. + *img.shields.io*) continue ;; + # Documented placeholders, not hosts. + *example.com*|*example.org*|*example.net*|*localhost*|*127.0.0.1*|*.invalid*) continue ;; + # This site's own pages: they exist only once this workflow + # has deployed them, and the offline check above already + # proves every link inside the site. + *go-scikit.github.io/docs*) continue ;; + # This repository's own files: on a pull request that adds + # them, they are not on main yet. + *github.com/go-scikit/docs/*) continue ;; + esac + # github.com answers curl's blob pages with 503 most of the time, + # while the raw host answers 200 for a file and 404 for a missing + # one. A blob link claims "this file exists at this ref", so ask + # the raw host (as the landing's links.yml and go-ndarray/docs#30). + probe=$u + case "$u" in + https://github.com/*/*/blob/*) + probe=https://raw.githubusercontent.com/$(printf '%s' "${u#https://github.com/}" | sed -E 's#^([^/]+/[^/]+)/blob/#\1/#; s/[?#].*$//') ;; + esac + # Three attempts: one is a flake detector rather than a link + # checker, and a lane that fails at random gets ignored. + code=000 + for _ in 1 2 3; do + code=$(curl -sS -o /dev/null -w '%{http_code}' -L --max-time 25 "$probe" 2>/dev/null) || true + code=${code:-000} + case "$code" in 2*|3*) break ;; esac + sleep 3 + done + case "$code" in + 2*|3*) printf ' ok %s %s\n' "$code" "$u" ;; + *) printf ' FAIL %s %s\n' "$code" "$u"; fail=1 ;; + esac + done <<< "$urls" + test "$fail" -eq 0 || { echo "::error::at least one link does not resolve"; exit 1; } + + deploy: + # Only main publishes. A pull request stops after build above: it has no + # business pushing to gh-pages. + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' + needs: build + # Never two deploys at once: both would push gh-pages and the second would + # be rejected. cancel-in-progress stays false -- killing a publish half way + # through is worse than making it wait. + concurrency: + group: gh-pages-deploy + cancel-in-progress: false + runs-on: ubuntu-latest + permissions: + contents: write + steps: + # The publishing script, from the commit being published. + - uses: actions/checkout@v7 + with: + path: source + + # The published site. Only the version being built is replaced; every + # other version stays as it is. The first deploy finds no gh-pages + # branch and starts it empty (orphan): nothing else ever creates it. + - uses: actions/checkout@v7 + with: + path: gh-pages + fetch-depth: 0 + + - name: Switch to gh-pages + working-directory: gh-pages + run: | + if git ls-remote --exit-code --heads origin gh-pages >/dev/null; then + git fetch -q origin gh-pages + git checkout -q -B gh-pages FETCH_HEAD + else + echo "no gh-pages branch yet: starting one" + git checkout -q --orphan gh-pages + git rm -rqf . + git clean -fdxq + fi + + - uses: actions/download-artifact@v8 + with: + name: site + path: site + + - name: Publish ${{ needs.build.outputs.version }} + run: source/scripts/publish-version.sh "${{ needs.build.outputs.version }}" site gh-pages + + - name: Push gh-pages + working-directory: gh-pages + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + if git diff --cached --quiet; then + echo "nothing changed" + exit 0 + fi + git commit -q -m "Deployed ${GITHUB_SHA::7} to ${{ needs.build.outputs.version }} with Hugo ${HUGO_VERSION}" + git push origin HEAD:gh-pages diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cd05fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/public/ +/resources/ +/_check/ +.hugo_build.lock +.DS_Store + +# Written by themes/hextra/scripts/page-history.sh before each build (CI and local). +/data/pagehistory.json diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1483162 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "themes/hextra"] + path = themes/hextra + url = https://github.com/tannevaled/hextra.git +[submodule "branding"] + path = branding + url = https://github.com/go-scikit/brand.git diff --git a/README.md b/README.md index 1a05060..2a0c379 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ -# docs -Documentation site for the go-scikit scientific stack for Go +# go-scikit/docs + +The documentation site of the [go-scikit](https://github.com/go-scikit) +umbrella, served at . + +Hugo with the [tannevaled/hextra](https://github.com/tannevaled/hextra) fork +(submodule `themes/hextra`, pinned at v0.16.0) and the +[go-scikit/brand](https://github.com/go-scikit/brand) marks (submodule +`branding`). Each documentation version is a separate build published to the +`gh-pages` branch by `.github/workflows/docs.yml`; the version label is the +newest minor among `params.libraries` in `hugo.yaml`. + +- Landing: +- Roadmap and status: + +## Build + +```sh +git submodule update --init +sh themes/hextra/scripts/page-history.sh > data/pagehistory.json +hugo server +``` + +BSD-3-Clause. diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..9500cf5 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,35 @@ +/* go-scikit branding on Hextra (github.com/go-scikit/brand). + * + * The mark's gradient, #8FA3C8 -> #2F3E63 (branding/svg/color/go-scikit.svg). + * Hextra derives its whole primary scale (links, active sidebar entry, + * buttons) from these three variables. + * + * Light theme: #2F3E63 = hsl(223 36% 29%), the gradient's dark end + * (10.55:1 on white). + * Dark theme: #8FA3C8 = hsl(219 34% 67%), its light end. */ +:root { + --primary-hue: 223deg; + --primary-saturation: 36%; + --primary-lightness: 29%; +} +.dark { + --primary-hue: 219deg; + --primary-saturation: 34%; + --primary-lightness: 67%; +} + +/* Tables: their headers stand out in the brand colour and their text is a + * size smaller than the prose. In the dark theme the header keeps the dark + * end: white on #8FA3C8 cannot be read. */ +.content table { font-size: 0.875em; } +.content table th { background: #2F3E63; color: #fff; } + +/* The version selector's list hangs from its button's right edge, so that it + * stays on screen at the end of the navbar. */ +.fs-version-select .hextra-nav-menu-items { left: auto !important; right: 0; transform: none !important; } + +/* The outdated-version banner (layouts/_partials/custom/content-begin.html). */ +.nd-outdated { margin-top: 1rem; padding: 0.75rem 1rem; border-radius: 0.5rem; + border: 1px solid #f59e0b; background: #fffbeb; color: #78350f; } +.dark .nd-outdated { background: #451a03; color: #fde68a; border-color: #b45309; } +.nd-outdated a { text-decoration: underline; font-weight: 600; } diff --git a/branding b/branding new file mode 160000 index 0000000..8d643b0 --- /dev/null +++ b/branding @@ -0,0 +1 @@ +Subproject commit 8d643b05f16db729037fc0f31e578212ca190a44 diff --git a/content/en/_index.md b/content/en/_index.md new file mode 100644 index 0000000..3c373d5 --- /dev/null +++ b/content/en/_index.md @@ -0,0 +1,53 @@ +--- +title: "go-scikit documentation" +linkTitle: "Home" +type: docs +cascade: + type: docs +description: "The scientific stack for Go, in pure Go (CGO=0), and the organisations that extend it towards MATLAB and Mathematica." +--- + +**go-scikit is the umbrella over the organisations that make up a scientific +stack for Go.** Each one is a library, or a few, with its own site, +documentation and release cycle. There is no cgo and no C library: one +`go build` gives a static binary. Where a library is slower or less accurate +than its Python reference, its own documentation says so. + +## The established organisations + +| Organisation | What it is | Landing | Documentation | +| --- | --- | --- | --- | +| [go-ndarray](https://github.com/go-ndarray) | N-dimensional arrays, `numpy.linalg`, `numpy.fft`, `numpy.random` | [site](https://go-ndarray.github.io/) | [docs](https://go-ndarray.github.io/docs/) | +| [go-fft](https://github.com/go-fft) | `numpy.fft` and `scipy.fft` equivalents | [site](https://go-fft.github.io/) | [docs](https://go-fft.github.io/docs/) | +| [go-numerics](https://github.com/go-numerics) | optimisation, quadrature and ODE solvers, special functions | [site](https://go-numerics.github.io/) | [docs](https://go-numerics.github.io/docs/) | +| [go-statistics](https://github.com/go-statistics) | distributions, descriptive statistics, statistical tests | [site](https://go-statistics.github.io/) | [docs](https://go-statistics.github.io/docs/) | +| [go-dataframe](https://github.com/go-dataframe) | labelled tables | [site](https://go-dataframe.github.io/) | [docs](https://go-dataframe.github.io/docs/) | +| [go-plot](https://github.com/go-plot) | matplotlib-class figures | [site](https://go-plot.github.io/) | [docs](https://go-plot.github.io/docs/) | +| [go-notebook](https://github.com/go-notebook) | compiled, reactive Go notebooks | [site](https://go-notebook.github.io/) | [docs](https://go-notebook.github.io/docs/) | + +## The parity-plan organisations + +The [roadmap](https://github.com/go-scikit/roadmap) plans feature parity with +MATLAB and Mathematica. Wave 1 is under way, in four organisations: + +| Organisation | Package | Status | Pages | +| --- | --- | --- | --- | +| go-approx | [interp](https://github.com/go-approx/interp) | released v0.1.0 | [go-approx]({{< relref "approx" >}}) | +| go-approx | [poly](https://github.com/go-approx/poly) | released v0.1.0 | [go-approx]({{< relref "approx" >}}) | +| go-dsp | [signal](https://github.com/go-dsp/signal) | released v0.1.0 | [go-dsp]({{< relref "dsp" >}}) | +| go-sparse | [sparse](https://github.com/go-sparse/sparse) | released v0.1.0 | [go-sparse]({{< relref "sparse" >}}) | +| go-bignum | [bigfloat](https://github.com/go-bignum/bigfloat) | in development, not yet tagged | [go-bignum]({{< relref "bignum" >}}) | + +The other organisations of the plan (go-symbolic, go-mlkit, go-autodiff, +go-geometry, go-fem, go-graphalgo, go-control, go-units, go-sciio) are +planned; nothing is released there. + +"Released" means a tag exists. The status of every item, with its evidence, is +in [STATUS.md](https://github.com/go-scikit/roadmap/blob/main/STATUS.md). + +## Where else + +- The portal: [go-scikit.github.io](https://go-scikit.github.io/). +- The plan: [go-scikit/roadmap](https://github.com/go-scikit/roadmap) (PLAN.md, + STATUS.md, bibliography). +- The marks: [go-scikit/brand](https://github.com/go-scikit/brand). diff --git a/content/en/approx.md b/content/en/approx.md new file mode 100644 index 0000000..0db04fc --- /dev/null +++ b/content/en/approx.md @@ -0,0 +1,27 @@ +--- +title: "go-approx" +description: "Interpolation, splines and polynomials. interp and poly are released v0.1.0." +--- + +go-approx is the home of approximation in the parity plan: interpolation, +splines, polynomials, and later Chebyshev and AAA approximation and scattered +data. + +| Package | Status | Repository | +| --- | --- | --- | +| interp | released v0.1.0 | [go-approx/interp](https://github.com/go-approx/interp) | +| poly | released v0.1.0 | [go-approx/poly](https://github.com/go-approx/poly) | + +## What is verified + +From [STATUS.md](https://github.com/go-scikit/roadmap/blob/main/STATUS.md): +`numpy.interp`, `interp1d`, PCHIP, Akima and `poly1d` are bit-identical to +NumPy and SciPy; splines agree within 1e-15 to 1e-10. The remaining `interp` +gaps are in progress. The speed comparison with the Python reference is in +[interp's docs/perf.md](https://github.com/go-approx/interp/blob/main/docs/perf.md). + +## Where to read more + +- Landing: [go-approx.github.io](https://go-approx.github.io/) +- Documentation: [go-approx.github.io/docs](https://go-approx.github.io/docs/) +- Organisation: [github.com/go-approx](https://github.com/go-approx) diff --git a/content/en/bignum.md b/content/en/bignum.md new file mode 100644 index 0000000..cff09f6 --- /dev/null +++ b/content/en/bignum.md @@ -0,0 +1,24 @@ +--- +title: "go-bignum" +description: "Correctly rounded big.Float functions and a Go oracle harness. bigfloat is in development." +--- + +go-bignum is the home of arbitrary precision in the parity plan: correctly +rounded `big.Float` functions, number theory, and the Go oracle harness. + +| Package | Status | Repository | +| --- | --- | --- | +| bigfloat | in development, not yet tagged | [go-bignum/bigfloat](https://github.com/go-bignum/bigfloat) | + +## State + +From [STATUS.md](https://github.com/go-scikit/roadmap/blob/main/STATUS.md): +the error model, the Ziv loop, roots, constants, and exp and log are done; +trigonometric, hyperbolic and power functions are in progress. No release has +been tagged. + +## Where to read more + +- Landing: [go-bignum.github.io](https://go-bignum.github.io/) +- Documentation: [go-bignum.github.io/docs](https://go-bignum.github.io/docs/) +- Organisation: [github.com/go-bignum](https://github.com/go-bignum) diff --git a/content/en/dsp.md b/content/en/dsp.md new file mode 100644 index 0000000..4196d1c --- /dev/null +++ b/content/en/dsp.md @@ -0,0 +1,18 @@ +--- +title: "go-dsp" +description: "Filter design, filtering and spectral estimation. signal is released v0.1.0." +--- + +go-dsp is the home of signal processing in the parity plan: filter design and +filtering, spectral estimation, and later resampling, wavelets and audio I/O. + +| Package | Status | Repository | +| --- | --- | --- | +| signal | released v0.1.0 | [go-dsp/signal](https://github.com/go-dsp/signal) | + +## Where to read more + +- Landing: [go-dsp.github.io](https://go-dsp.github.io/) +- Documentation: [go-dsp.github.io/docs](https://go-dsp.github.io/docs/) +- Organisation: [github.com/go-dsp](https://github.com/go-dsp) +- Status of every item: [STATUS.md](https://github.com/go-scikit/roadmap/blob/main/STATUS.md) diff --git a/content/en/sparse.md b/content/en/sparse.md new file mode 100644 index 0000000..50b22f9 --- /dev/null +++ b/content/en/sparse.md @@ -0,0 +1,23 @@ +--- +title: "go-sparse" +description: "Sparse containers, orderings and iterative solvers. sparse is released v0.1.0." +--- + +go-sparse is the home of sparse linear algebra in the parity plan: sparse +containers, orderings, iterative solvers, and later direct solvers and sparse +eigensolvers. + +| Package | Status | Repository | +| --- | --- | --- | +| sparse | released v0.1.0 | [go-sparse/sparse](https://github.com/go-sparse/sparse) | + +## What is verified + +From [STATUS.md](https://github.com/go-scikit/roadmap/blob/main/STATUS.md): +iteration counts equal SciPy's for CG, GMRES, MINRES and LSQR. + +## Where to read more + +- Landing: [go-sparse.github.io](https://go-sparse.github.io/) +- Documentation: [go-sparse.github.io/docs](https://go-sparse.github.io/docs/) +- Organisation: [github.com/go-sparse](https://github.com/go-sparse) diff --git a/hugo.yaml b/hugo.yaml new file mode 100644 index 0000000..45866f7 --- /dev/null +++ b/hugo.yaml @@ -0,0 +1,161 @@ +# go-scikit documentation (Hugo + Hextra), built like go-numerics/docs. +# +# Each documentation version is a separate build under +# https://go-scikit.github.io/docs//, where is the newest +# minor version among the libraries the pages describe (0.1, 0.2, ...), or +# "main" while none of them is tagged. The CI sets it through --baseURL, from +# params.libraries below. This default is the same build. +baseURL: "https://go-scikit.github.io/docs/0.1/" +title: "go-scikit" +# themes/hextra is the tannevaled/hextra fork, pinned at a release tag +# (v0.16.0): upstream Hextra plus opt-in features (partial menu items, combos, +# related-sites menu, page subtitle and history, darkreaderLock). +theme: hextra + +# English is the default language and stays at the root of each version. +defaultContentLanguage: en +defaultContentLanguageInSubdir: false + +languages: + en: + label: "English" + contentDir: content/en + weight: 1 + +enableRobotsTXT: true +# Git history dates every page: "Last updated on" at the bottom of each page. +enableGitInfo: true + +markup: + goldmark: + renderer: + unsafe: true + parser: + attribute: + title: true + highlight: + noClasses: false + +module: + hugoVersion: + extended: false + min: 0.146.0 + # The marks and favicons come from the go-scikit brand repository + # (submodule branding/), published under /images/brand/. Only the org mark's + # colour formats are mounted. + mounts: + - source: static + target: static + - source: assets + target: assets + - source: branding/svg/color + target: static/images/brand/svg + files: ["go-scikit.svg"] + - source: branding/png/color + target: static/images/brand/png + files: ["*/go-scikit.png"] + - source: branding/ico + target: static/images/brand/ico + files: ["go-scikit.ico"] + +menu: + main: + # Navbar, left to right: version, theme, search, sources. + - name: Version + weight: 3 + params: + type: partial + partial: custom/version-select.html + - name: Theme + weight: 4 + params: + type: theme-toggle + combo: true + - name: Search + weight: 5 + params: + type: search + - name: GitHub + url: https://github.com/go-scikit + weight: 6 + params: + icon: github + +params: + description: "The scientific stack for Go, in pure Go (CGO=0): arrays, FFTs, optimisation, statistics, tables, figures and notebooks, and the organisations that extend it towards MATLAB and Mathematica." + + # The release of each library these pages describe, for the member + # organisations that are new in the parity plan. The newest minor version + # among them is the documentation's version label (v0.1.0 -> 0.1): the CI + # reads it here. bigfloat has no tag yet, so it is "main". + libraries: + interp: "v0.1.0" + poly: "v0.1.0" + signal: "v0.1.0" + sparse: "v0.1.0" + bigfloat: "main" + versions: + # The version selector shows "main" with the development icon. + development: "main" + + navbar: + displayTitle: true + displayLogo: true + logo: + path: images/brand/svg/go-scikit.svg + dark: images/brand/svg/go-scikit.svg + width: 32 + height: 32 + # Related sites, opened from the chevron beside the title (the logo itself + # leads to the documentation's home). + menu: + - name: go-scikit + url: https://go-scikit.github.io/ + logo: images/brand/svg/go-scikit.svg + + theme: + default: system + # The theme toggle is in the navbar (menu above), not at the foot of the sidebar. + displayToggle: false + # Dark Reader would darken the light theme itself; with the lock, the dark + # theme is our own. + darkreaderLock: true + + footer: + enable: true + displayCopyright: true + displayPoweredBy: false + + displayUpdatedDate: true + dateFormat: "January 2, 2006" + + editURL: + enable: true + base: "/go-scikit/docs/edit/main/content" + + toc: + displayTags: true + + page: + width: normal + # The front matter description as a subtitle under the title. + displayDescription: true + # "Created on ... by ... · Modified on ... by ..." at the foot of each page: + # creation from data/pagehistory.json, which the build writes with + # themes/hextra/scripts/page-history.sh (it needs the full git history); + # modification from git (enableGitInfo). + history: true + contextMenu: + enable: false + + highlight: + copy: + enable: true + display: hover + + search: + enable: true + type: flexsearch + flexsearch: + index: content + tokenize: forward diff --git a/i18n/en.yaml b/i18n/en.yaml new file mode 100644 index 0000000..f71b3c7 --- /dev/null +++ b/i18n/en.yaml @@ -0,0 +1,5 @@ +# Site strings beside Hextra's own (themes/hextra/i18n/en.yaml). +copyright: "© 2026 the go-scikit authors · BSD-3-Clause" +version: "Version" +outdated: "You are reading the documentation of an outdated version, whose text may no longer be accurate." +outdatedLink: "Go to the latest version." diff --git a/layouts/_partials/custom/content-begin.html b/layouts/_partials/custom/content-begin.html new file mode 100644 index 0000000..9dd6dee --- /dev/null +++ b/layouts/_partials/custom/content-begin.html @@ -0,0 +1,30 @@ +{{- /* Outdated-version banner, as the MkDocs site had (overrides/main.html). + + A build cannot know whether a newer version was published after it, so the + banner is hidden and the browser reveals it when /versions.json + gives the alias "latest" to another version than this one. The link goes to + the docs root, which redirects to latest/; it is set with the banner, so + the offline link check (where only this version exists) never sees it. */ -}} +{{- $basePath := strings.TrimSuffix "/" (urls.Parse site.BaseURL).Path -}} +{{- $current := path.Base $basePath -}} +{{- $docsRoot := printf "%s/" (strings.TrimSuffix "/" (path.Dir $basePath)) -}} + + diff --git a/layouts/_partials/custom/version-select.html b/layouts/_partials/custom/version-select.html new file mode 100644 index 0000000..295f4fb --- /dev/null +++ b/layouts/_partials/custom/version-select.html @@ -0,0 +1,118 @@ +{{- /* Navbar version selector, as in go-fileshare/docs and claimward/docs. + + Each documentation version is a separate build published under + //, where is the documentation version (the newest minor of the go-scikit member libraries) the + pages describe (0.1, ...), or "main" until the first release, and its + baseURL ends with that version. A build cannot know the versions published + after it, so the server renders only the current one; in the browser the + list is filled from /versions.json, which the deploy job rewrites + in the format mike writes (version, title, aliases, properties). + + The site is ready for several languages: English at the root of a version, + the others under their code (/fr/...). Each option opens, in that + version, the first of these that exists: the current page in the current + language; the same page in English; the home in the current language; the + version's home. A page that a version does not have therefore never ends on + a 404. The language prefix is read from the home's permalink, not guessed + from the URL. + + Built on Hextra's own navbar dropdown (assets/js/core/nav-menu.js), so its + keyboard handling applies. */ -}} +{{- $page := . -}} +{{- $basePath := strings.TrimSuffix "/" (urls.Parse site.BaseURL).Path -}} +{{- $current := path.Base $basePath -}} +{{- $docsRoot := printf "%s/" (strings.TrimSuffix "/" (path.Dir $basePath)) -}} +{{- $versionRoot := printf "%s%s/" $docsRoot $current -}} +{{- $rest := strings.TrimPrefix $versionRoot $page.RelPermalink -}} +{{- /* "fr/" in French, "" in English (the default language, at the root). */ -}} +{{- $langPrefix := strings.TrimPrefix $versionRoot site.Home.RelPermalink -}} +{{- /* The same page in the default language: same file names in every content//. */ -}} +{{- $restDefault := cond (ne $langPrefix "") (strings.TrimPrefix $langPrefix $rest) $rest -}} +{{- $dev := site.Params.versions.development | default "dev" -}} +{{- $itemClass := "hx:text-gray-600 hx:hover:text-gray-800 hx:dark:text-gray-400 hx:dark:hover:text-gray-200 hx:relative hx:cursor-pointer hx:whitespace-nowrap hx:rounded-sm hx:py-1.5 hx:transition-colors hx:ltr:pl-3 hx:ltr:pr-9 hx:rtl:pr-3 hx:rtl:pl-9 hx:flex hx:items-center hx:gap-1 hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800" -}} +{{- $iconAttrs := `height="1em" class="hx:inline-block"` -}} +
+ + + + + +
+ diff --git a/layouts/_partials/favicons.html b/layouts/_partials/favicons.html new file mode 100644 index 0000000..1a79648 --- /dev/null +++ b/layouts/_partials/favicons.html @@ -0,0 +1,8 @@ +{{- /* The favicons are the go-scikit brand's org mark (submodule branding/, + mounted under /images/brand/ by hugo.yaml) rather than files copied into + static/. Replaces Hextra's favicons.html, which expects them at the root. */ -}} + + + + + diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..123150f --- /dev/null +++ b/renovate.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["github>go-scikit/.github"] +} diff --git a/scripts/publish-version.sh b/scripts/publish-version.sh new file mode 100755 index 0000000..de334bd --- /dev/null +++ b/scripts/publish-version.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# Publish one documentation build into a checkout of the gh-pages branch. +# +# scripts/publish-version.sh +# +# is the documentation version the build describes, MAJOR.MINOR +# (0.1): the newest minor version among the go-scikit member libraries it +# documents, or "main" while none of them is tagged. The build replaces +# // and nothing else: every other version already +# published is kept as it is. Then, from the directories present: +# +# versions.json rewritten in mike's format ({version, title, aliases}), +# newest release first, "main" last; the version selector +# reads it; +# latest a symbolic link to the newest release, or to "main" when +# no release has been published yet; +# index.html the root, redirecting to latest/ (as mike made it). +# +# Needs jq and rsync. Commits nothing: the workflow does. +set -eu + +die() { echo "publish-version.sh: $*" >&2; exit 1; } + +[ $# -eq 3 ] || die "usage: $0 " +version=$1 +site=$2 +pages=$3 +label='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$' + +[ "$version" = main ] || printf '%s\n' "$version" | grep -Eq "$label" || die "version must be MAJOR.MINOR (0.1) or main, not \"$version\"" +[ -f "$site/index.html" ] || die "$site/index.html is missing: build the site first" +[ -d "$pages" ] || die "$pages is not a directory" +command -v jq >/dev/null || die "jq is required" +command -v rsync >/dev/null || die "rsync is required" + +# The version's own directory, replaced whole. A real directory: if it was a +# link (an alias), the link goes, not what it pointed to. +[ -L "$pages/$version" ] && rm "$pages/$version" +mkdir -p "$pages/$version" +rsync -a --delete "$site/" "$pages/$version/" + +# The versions present, newest first (0.10 before 0.9: compared as numbers), +# then "main". latest is the newest release, else main. +versions=$(cd "$pages" && for d in *; do + [ -d "$d" ] && [ ! -L "$d" ] && printf '%s\n' "$d" | grep -Eq "$label" && printf '%s\n' "$d" +done | sort -t. -k1,1nr -k2,2nr) +[ -d "$pages/main" ] && [ ! -L "$pages/main" ] && versions=$(printf '%s\n%s\n' "$versions" main | sed '/^$/d') +latest=$(printf '%s\n' "$versions" | sed -n 1p) + +# versions.json: the newest carries the alias "latest". +for v in $versions; do + if [ "$v" = "$latest" ]; then + jq -n --arg v "$v" '{version: $v, title: $v, aliases: ["latest"]}' + elif [ "$v" = main ]; then + jq -n --arg v "$v" '{version: $v, title: $v, aliases: [], properties: {development: true}}' + else + jq -n --arg v "$v" '{version: $v, title: $v, aliases: []}' + fi +done | jq -s . >"$pages/versions.json.tmp" +mv "$pages/versions.json.tmp" "$pages/versions.json" + +# latest -> the newest version, and the root redirect. +rm -rf "$pages/latest" +ln -s "$latest" "$pages/latest" +cat >"$pages/index.html" <<'EOF' + + + + + Redirecting + + + + + Redirecting to latest/... + + +EOF +touch "$pages/.nojekyll" + +echo "published $version; latest is $latest; versions: $(jq -r '[.[].version] | join(", ")' "$pages/versions.json")" diff --git a/themes/hextra b/themes/hextra new file mode 160000 index 0000000..1d8daa4 --- /dev/null +++ b/themes/hextra @@ -0,0 +1 @@ +Subproject commit 1d8daa42d0406250fa00b7e803db2ab104a7fcab