Skip to content

feat(doc): live demos for all demos/* - #46

Merged
JumpLink merged 16 commits into
mainfrom
feat/live-demos
Oct 4, 2026
Merged

JumpLink merged 16 commits into
mainfrom
feat/live-demos

Conversation

@JumpLink

@JumpLink JumpLink commented Oct 4, 2026

Copy link
Copy Markdown

Builds all 45 demos/* into the docs site (/demos/<id>/), adds a gallery (demos.html) and an iframe viewer (demo.html?id=<id>).

  • build:demos registry + manifest, hardened against Rolldown build deadlocks
  • basePathPlugin in infra/vite-config: prefixes root-absolute asset paths with the Vite base
  • smoke:demos: headless Chromium loads every demo; wired into deploy-docs.yml before the Pages upload
  • Demo fixes: bs5-tagged-image, router-view, podcast x2, iconset
  • Docs: infra/doc/README.md

Local: build:demos 45/45, smoke 45 ok, yarn test 874 green. yarn test:e2e could not start locally (Playwright loader error), so CI is the first real run of it.
A merge to main deploys ribajs.com.

Pascal Garber and others added 16 commits October 4, 2026 10:25
Adds infra/doc/scripts/build-demos.js: discovers every demos/* with a
package.json, builds it with a site-root-relative base into _demos/<id>,
and records title/description/category/entries/sizeKB/status/knownIssues
in _demos/manifest.json. A failed build is recorded, not fatal.

The doc build copies _demos into _site/demos via a writeBundle plugin,
because build.emptyOutDir would otherwise drop them. loadLocals() feeds
the manifest to the Pug templates as `demos`.

Rolldown deadlocks intermittently under parallel builds (all worker
threads block while the main thread idles), so a timed-out demo build is
retried once, and a build is killed by its --outDir marker in case the
grandchild outlives its reparented process group.
demos.pug lists every demo from the build manifest, grouped by
category with a status badge per card. demo.pug embeds one demo in an
iframe with device widths, reload, standalone and GitHub links, plus a
banner for demos with known issues.

A static host cannot resolve the ?id= query, so demo.pug embeds the
manifest as a JSON snapshot and rv-demo-viewer looks the demo up in the
browser. CODE is one of Riba's blockNodeNames, so a binder on <code>
would never bind; the fallback uses a styled span instead.
watch-demos.js rebuilds only the changed demo into _site/demos/<id>
instead of running the whole doc build, watching demos/*/src,
demos/*/public and infra/vite-config (a change there dirties all
demos). start:live runs the doc watch, the demo watch and a preview on
127.0.0.1:4173.

It carries over the hardening from build-demos.js: a rolldown deadlock
hangs a build without ever settling, so every demo build has a timeout
and one retry, and stray vite builds are swept by their --outDir marker.
Demos carry hardcoded root-absolute references such as /iconset/svg/…
and /images/… in their component templates. Vite's --base does not
rewrite those, so every demo built for a subpath 404s on its own
assets. The plugin prefixes them in generateBundle whenever base is not
'/', and stays inactive for a plain root build so `vite` in a demo
directory is unchanged.

The rewrite is limited to the public directory's top-level entries plus
the roots the iconset plugin emits, and only behind a quote or bracket,
so protocol-relative and absolute URLs are left alone. Rolldown keeps
chunk text in chunk.code rather than chunk.source.
The sweep matched on the shared `_demos` output root, so one demo hitting
its timeout killed every sibling build running at that moment and turned
healthy demos into build-failed entries. The marker now names the single
demo's outDir; the whole tree is only swept at startup, when none of our
own builds are running.

Also lifts resolveSiteBase() into scripts/site-base.js. Both scripts build
the same demos, and a drift between two copies of the base would make the
full build and the incremental watch disagree on their asset URLs.
Both demos relied on being served at the site root. bs5-tagged-image
climbed with ../../../images/ (the browser cannot climb above /, so it
only worked there) and pointed its slideshow icons at SVGs that Vite never
emits. router-view linked its pages root-absolute. Use /images/ and
/iconset/svg/ so the base path plugin applies, and relative page links.
The fonts and images lived in src/assets but were only referenced from
strings, so Vite never emitted them and every request 404ed. Move them to
public/assets, where /assets/... and ./assets/... resolve, and fix the
show poster path that pointed to a non-existent web-player/ subfolder.
import.meta.glob with a bare package specifier is left untransformed by
Vite 8, which crashed the demo at load. Use a path relative to the file.
imgur answers hotlinked images with 403 when the Referer is an IP literal, so the demo showed broken images on 127.0.0.1. Without a referrer it answers 200 everywhere.
The demo links its pages as ./page-1.html now so it also works under a subpath; the selectors matched the old root-absolute href.
@JumpLink
JumpLink merged commit d417b0f into main Oct 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant