Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 56 additions & 12 deletions .github/workflows/site.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
name: Site

# Builds the organization site on every pull request, and publishes it to
# GitHub Pages from main. The generator lives in jlt-commons/docs-engine,
# shared with every project site; this repo owns its content in docs/, its
# config in docs/site.edn, and its homepage template.
#
# The engine is pinned to a tag rather than tracking its main branch, so a
# change over there cannot take this site down without someone choosing it.

on:
push:
branches: [main]
Expand All @@ -9,34 +17,70 @@ on:
permissions:
contents: read

# Never let two deploys race. Do not cancel a running deploy, since a
# half-applied Pages deployment is worse than a slightly stale one.
# Deploys must not race, and a half-applied Pages deployment is worse than
# a slightly stale one, so main is never cancelled. Pull request builds are
# scoped per ref and cancel their own earlier runs, so a third queued run
# cannot supersede a second one and show a contributor a cancelled check.
concurrency:
group: pages
cancel-in-progress: false
group: site-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

env:
DOCS_ENGINE_REF: v0.2.0

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: Check out the docs engine
uses: actions/checkout@v7
with:
repository: jlt-commons/docs-engine
ref: ${{ env.DOCS_ENGINE_REF }}
path: .docs-engine

- name: Install babashka
uses: DeLaGuardo/setup-clojure@13.6.1
with:
bb: latest

- name: Test
run: bb test

- name: Build
run: bb build
working-directory: .docs-engine
run: bb build "$GITHUB_WORKSPACE"

- name: Check the build is not empty
- name: Check the build
run: |
test -f _site/index.html || { echo "no index.html generated"; exit 1; }
test -f _site/css/screen.css || { echo "static assets missing"; exit 1; }
! grep -q '{{site-base}}' _site/index.html || { echo "unrendered template variable"; exit 1; }
set -euo pipefail
out=_site

test -f "$out/index.html" || { echo "no homepage generated"; exit 1; }
test -f "$out/guide/index.html" || { echo "no guide page generated"; exit 1; }
test -f "$out/css/screen.css" || { echo "static assets missing"; exit 1; }
test -f "$out/img/mark.svg" || { echo "the mark was not copied — check :asset-dirs"; exit 1; }

! grep -rq '{{site-base}}' "$out"/index.html "$out"/guide/*.html \
|| { echo "unrendered template variable"; exit 1; }

# This site is served at the domain ROOT, so its URLs are correctly
# root-absolute. That is the opposite of a project site, where a bare
# /css/... would resolve here instead of inside the project. The
# check that belongs here is that no project's base path leaked in.
if grep -ohE '(href|src)="/[a-z-]+/' "$out"/index.html "$out"/guide/*.html \
| sort -u | grep -vE '="/(css|img|guide|vendor)/'; then
echo "the paths above are not this site's own"
exit 1
fi

# The engine loads mermaid only where a diagram exists. This site has
# none, and the bundle is 3.4 MB, so its appearance means the gating
# regressed rather than that someone added a diagram — which would
# also need this line updated, deliberately.
! grep -rq 'mermaid.min.js' "$out"/index.html "$out"/guide/*.html \
|| { echo "mermaid loaded on a site with no diagrams"; exit 1; }

echo "build looks correct"

- name: Upload the Pages artifact
if: github.ref == 'refs/heads/main'
Expand Down
85 changes: 50 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,71 @@
# jlt-commons.github.io

The [jlt-commons](https://github.com/jlt-commons) website, and the small static-site
generator that builds it.
The [jlt-commons](https://github.com/jlt-commons) website.

Live at **https://jlt-commons.github.io**.

## Building it
## What's here

You need [babashka](https://babashka.org). Nothing else; the only external dependency is
`markdown-clj`, fetched on first run.
Content, and nothing else. The generator moved out to
[jlt-commons/docs-engine](https://github.com/jlt-commons/docs-engine), which is
shared with every project site in the organization.

```bash
bb test # run the test suite
bb build # generate the site into _site/
bb serve # build, then serve at http://localhost:3000
bb clean # delete _site/
```

`_site/` is generated and is not committed. GitHub Actions builds and deploys on every
push to `main`, and runs the tests on every pull request.
docs/
site.edn # configuration
guide/ # pages, in markdown
templates/home.html # the homepage
img/ # the mark
```

## Editing content

Pages are markdown under `content/guide/`. Add a file and it appears in the nav
automatically, with `index.md` pinned first. The homepage is a hand-written template at
`resources/templates/home.html`.
Pages are markdown under `docs/guide/`. Add a file and it appears in the nav
automatically, with `index.md` pinned first. The homepage is a hand-written
template at `docs/templates/home.html`.

Governance text is deliberately **not** duplicated here. This site links to the canonical
documents in [`meta`](https://github.com/jlt-commons/meta), because two copies of a rule
become two different rules.
Governance text is deliberately **not** duplicated here. This site links to the
canonical documents in [`meta`](https://github.com/jlt-commons/meta), because two
copies of a rule become two different rules.

Mermaid fences are not supported. `markdown.clj` still rewrites ```` ```mermaid ```` blocks
into `<pre class="mermaid">`, but the mermaid.js bundle that would render them isn't
vendored in this site, so a diagram renders as plain, unstyled source text.
## Building it

## Using this generator for your own project
CI builds the site on every pull request and deploys it from `main`, so a merged
change goes live without anyone running anything. That is the authority.

Any jlt-commons project is welcome to. Copy `src/`, `resources/`, `test/` and `bb.edn`,
then set `:base-path` in `src/site/config.clj` to your repo name:
To preview locally, clone the engine alongside this repo:

```clojure
:base-path "/your-repo"
```bash
git clone https://github.com/jlt-commons/docs-engine ../docs-engine
bb site:serve # build, then serve at http://localhost:3000
bb site:build # build into _site/ without serving
bb site:clean # delete _site/
```

That matters. A project site is served at `jlt-commons.github.io/your-repo/`, and without
a base path every stylesheet and nav link resolves against the organization site instead
of yours. The page still renders, which is what makes the bug easy to miss, so
`site.core-test` covers it.
`_site/` is generated and is not committed. The tasks print the clone command if
they cannot find an engine checkout; CI needs none of this, because it checks the
engine out itself at a pinned tag.

## Mermaid

Supported. A ```` ```mermaid ```` fence in a guide page renders as a diagram,
themed to match the reader's light or dark setting. The engine loads the bundle
only on pages that actually have one, since it is 3.4 MB against a typical page
of a few kilobytes.

This site currently has no diagrams, and its build checks that the bundle stays
absent. Adding one means updating that check, deliberately, in
`.github/workflows/site.yml`.

Leave `:base-path` as `""` only for a site served at a domain root.
## Using the engine for your own project

## Credit
Any jlt-commons project can. See the
[engine's README](https://github.com/jlt-commons/docs-engine#onboarding-a-project);
[`raylib-jlt`](https://github.com/jlt-commons/raylib-jlt) is a working example
with a bespoke homepage and an image gallery.

The generator is a trimmed port of a private engine by the same author, reduced to a
single site and extended with base-path support.
The one thing to get right is `:base-path`. This site sets `""` because it is
served at the domain root. A project site is served at
`jlt-commons.github.io/<repo>/` and sets `:base-path "/<repo>"`; without it every
stylesheet and nav link resolves against this site instead. The page still
renders, wearing the wrong clothes, which is what makes the bug easy to ship.
69 changes: 45 additions & 24 deletions bb.edn
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@
;; bb.edn - the jlt-commons website generator.
;; bb.edn — local preview for the jlt-commons organization site.
;;
;; A trimmed port of a private engine by the same author, reduced to a
;; single site. The one addition is base-path support (see
;; site.core/base-path), which lets a jlt-commons member project build a
;; site served at /<repo>/ rather than at a domain root.
{:paths ["src" "test" "resources"]
:deps {markdown-clj/markdown-clj {:mvn/version "1.11.4"}}
:tasks
{:requires ([site.config :as config])
;; The generator is not here. It lives in jlt-commons/docs-engine, shared
;; with every project site in the organization, and CI checks it out at a
;; pinned tag (.github/workflows/site.yml). These tasks exist only so the
;; site can be previewed without pushing, and they are the one place that
;; needs a checkout of the engine on disk.
{:tasks
{:requires ([babashka.fs :as fs])

test {:doc "Run the full test suite"
:requires ([clojure.test :as t]
[site.markdown-test]
[site.core-test])
:task (let [{:keys [fail error]} (t/run-tests 'site.markdown-test 'site.core-test)]
(when (pos? (+ fail error)) (System/exit 1)))}
:init
(do
(def docs-engine-repo "https://github.com/jlt-commons/docs-engine")

build {:doc "Generate the site into _site/"
:requires ([site.core :as core])
:task (core/generate! (config/site))}
(defn docs-engine-dir
"Where the engine is checked out: $JLT_DOCS_ENGINE, else a sibling
directory, else the usual spot. nil when none of them exist."
[]
(let [home (System/getProperty "user.home")]
(->> [(System/getenv "JLT_DOCS_ENGINE")
"../docs-engine"
(str home "/dev/jlt-commons/docs-engine")]
(remove nil?)
(filter (fn [d] (fs/exists? (fs/file d "bb.edn"))))
first)))

clean {:doc "Delete the _site/ build output"
:requires ([site.core :as core])
:task (core/clean! (config/site))}
(defn site-task
"Runs one of the engine's tasks against this site."
[task & args]
(if-let [engine (docs-engine-dir)]
(let [argv (into ["bb" task (str (fs/cwd))] (remove nil? args))
res (apply shell {:dir (str engine) :continue true} argv)]
(when-not (zero? (:exit res)) (System/exit (:exit res))))
(do
(println "The docs engine is not checked out anywhere I looked:")
(println " $JLT_DOCS_ENGINE, ../docs-engine, ~/dev/jlt-commons/docs-engine")
(println)
(println " git clone" docs-engine-repo "../docs-engine")
(println)
(println "CI does not need this — it checks the engine out itself.")
(System/exit 1)))))

serve {:doc "Build, then serve _site/ locally (bb serve [port], default 3000)"
:requires ([site.core :as core])
:task (core/serve! (config/site) (first *command-line-args*))}}}
site:build {:doc "Generate the site into _site/"
:task (site-task "build")}

site:serve {:doc "Build, then serve _site/ locally (bb site:serve [port], default 3000)"
:task (site-task "serve" (first *command-line-args*))}

site:clean {:doc "Delete the _site/ build output"
:task (site-task "clean")}}}
File renamed without changes.
File renamed without changes.
File renamed without changes
26 changes: 26 additions & 0 deletions docs/site.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
;; Configuration for the jlt-commons organization site, read by the shared
;; docs-engine (https://github.com/jlt-commons/docs-engine).
;;
;; Build it locally with `bb site:serve`. CI builds and publishes it from
;; .github/workflows/site.yml.
{;; Empty, because this site is served at the domain root,
;; https://jlt-commons.github.io. A member project is served at
;; https://jlt-commons.github.io/<repo>/ and sets :base-path "/<repo>"
;; instead. See site.core/base-path in the engine.
:base-path ""

:title "jlt-commons"
:description "A community-led home for Jolt libraries and tooling."

;; The organization, not this repository. The nav's GitHub link should
;; land on the org page rather than on the site's own source, which is
;; why this overrides the engine's derive-from-origin default.
:github-url "https://github.com/jlt-commons"

;; docs/img holds the mark the homepage renders. Engine static assets
;; (css, highlight.js, mermaid) come from the engine itself; anything
;; belonging to this site lives here.
:asset-dirs ["img"]

;; Relative to docs/templates/.
:home-template "home.html"}
File renamed without changes.
66 changes: 0 additions & 66 deletions resources/static/css/print.css

This file was deleted.

Loading