Skip to content

feat(rich-media): asciinema player for ::cast recordings (rich-media Task 4.1/4.2) - #3037

Merged
jung-thomas merged 4 commits into
DEVfrom
worktree-cast-player
Nov 6, 2026
Merged

jung-thomas merged 4 commits into
DEVfrom
worktree-cast-player

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

What / Why

Completes spec tasks 4.1 and 4.2 of the tutorial-rich-media-and-tables openspec. The `::cast` directive grammar was merged but nothing played — `hugo/assets/js/cast.ts` was a stub (`export {};`) and no player was vendored.

Changes

  • scripts/vendor-asciinema.mjs — downloads asciinema-player v3.18.0 (.min.js + .css) from GitHub releases into `hugo/static/js/vendor/` (gitignored, idempotent via versioned sentinel). Wired into `build:apps` and `setup`.
  • REUSE.toml — adds `asciinema-player.css` Apache-2.0 entry (JS entry was already present from the rich-media merge).
  • hugo/assets/js/cast.ts — replaces stub: IntersectionObserver-based lazy mount (rootMargin 200px). Loads player JS+CSS only when the first `.tut-cast` element approaches the viewport — tutorials without `::cast` ship zero extra bytes. Falls back to immediate mount when IO unavailable. Maps all data attributes to player opts (`idle-limit` → `idleTimeLimit`). Removes placeholder `
    ` after mount. Guards double-mount via `data-cast-mounted`.
  • hugo/assets/js/tests/cast.test.ts — 5 new unit tests (mount, no-double-mount, IO-fallback, idle-limit mapping, placeholder removal).
  • scripts/tests/vendor-asciinema.test.mjs — 2 tests (error exit on bad fetch, skip when sentinel present). Environment-independent via existsSync mock.
  • scripts/parsers/directives/tests/cast-diagram.test.ts — 1 new assertion pinning the shortcode attribute contract cast.ts relies on.
  • vitest.config.ts — extends unit include patterns to cover `.mjs` test files.

License

asciinema-player v3.18.0: Apache-2.0 (confirmed from source). REUSE.toml records both vendored files with `SPDX-License-Identifier: Apache-2.0` and `SPDX-FileCopyrightText: asciinema contributors`.

How tested

  • npx vitest run scripts/__tests__/vendor-asciinema.test.mjs — 2/2 pass
  • npx vitest run hugo/assets/js/__tests__/cast.test.ts — 5/5 pass
  • npx vitest run scripts/parsers/directives/__tests__/cast-diagram.test.ts — 6/6 pass
  • npx vitest run --project unit — full unit suite exits 0
  • node scripts/vendor-asciinema.mjs — confirmed downloads asciinema-player.min.js (226 KB) + asciinema-player.css (19 KB) from GitHub releases

Deploy scope

Frontend / Hugo only. No CAP server changes. No new npm runtime deps. The vendor:asciinema download runs during build:apps (part of build:all); CI already runs npm run build:all before Hugo.

…ntry

- Add scripts/vendor-asciinema.mjs: ESM download script for asciinema-player
  v3.18.0 JS + CSS from GitHub releases; idempotent via versioned sentinel
  file (.asciinema-vendored-3.18.0); guarded against test import side-effects
  via process.argv[1] check
- Add scripts/__tests__/vendor-asciinema.test.mjs: offline unit tests using
  vi.stubGlobal + vi.spyOn(fs); two cases: non-ok fetch exits 1, sentinel
  present skips download; fixed vi.stubGlobal return-value quirk by capturing
  mock fn before passing to stubGlobal (documented in test comment)
- Update vitest.config.ts: extend unit include patterns from {js,ts} to
  {js,mjs,ts} so .mjs test files are picked up
- Update package.json: add vendor:asciinema script; prepend to build:apps;
  append to setup
- Update REUSE.toml: add Apache-2.0 annotation for asciinema-player.css
@jung-thomas
jung-thomas merged commit 03d33c6 into DEV Nov 6, 2026
5 of 6 checks passed
@jung-thomas
jung-thomas deleted the worktree-cast-player branch November 6, 2026 16:50
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