Skip to content
Open
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
13 changes: 13 additions & 0 deletions .githooks/check-freeze.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ while IFS= read -r qmd; do
[ -n "$qmd" ] || continue
freeze_rel="_freeze/${qmd%.qmd}/execute-results/html.json"

# Skip when the freeze file is intentionally removed in this change: the
# page no longer executes code (e.g. converted to the markdown engine), so
# its freeze entry is vestigial and correctly deleted, not stale.
if [ "$MODE" = "commit" ]; then
if git diff --cached --diff-filter=D --name-only 2>/dev/null | grep -Fxq "$freeze_rel"; then
continue
fi
else
if git diff "${REMOTE}..HEAD" --diff-filter=D --name-only 2>/dev/null | grep -Fxq "$freeze_rel"; then
continue
fi
fi

# Read freeze JSON from git objects, not working tree, to avoid false passes
# when the freeze file is updated on disk but not yet staged.
if [ "$MODE" = "commit" ]; then
Expand Down
11 changes: 8 additions & 3 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,14 @@ jobs:
'docs/extensions/listings/custom-formats.yml': 'docs/extensions/index.html',
'docs/extensions/listings/revealjs-formats.yml': 'docs/extensions/index.html',
'docs/extensions/listings/revealjs.yml': 'docs/extensions/index.html',
// Gallery data files → gallery index
'docs/gallery/carousel.yml': 'docs/gallery/index.html',
'docs/gallery/gallery.yml': 'docs/gallery/index.html',
// Gallery data files → gallery pages
'docs/gallery/data/featured.yml': 'docs/gallery/index.html',
'docs/gallery/data/reports-analytics.yml': 'docs/gallery/reports-analytics.html',
'docs/gallery/data/dashboards-monitoring.yml': 'docs/gallery/dashboards-monitoring.html',
'docs/gallery/data/research-scholarship.yml': 'docs/gallery/research-scholarship.html',
'docs/gallery/data/teaching-learning.yml': 'docs/gallery/teaching-learning.html',
'docs/gallery/data/software-documentation.yml': 'docs/gallery/software-documentation.html',
'docs/gallery/data/personal-community.yml': 'docs/gallery/personal-community.html',
// Guide listing → guide index
'docs/guide/guide.yml': 'docs/guide/index.html',
// Download data → download index
Expand Down
15 changes: 0 additions & 15 deletions _freeze/docs/gallery/index/execute-results/html.json

This file was deleted.

17 changes: 15 additions & 2 deletions _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,19 @@ website:
- text: "Tutorial: Authoring"
href: docs/get-started/authoring/

- id: gallery
contents:
- section: "Gallery"
href: docs/gallery/index.qmd
contents:
- docs/gallery/reports-analytics.qmd
- docs/gallery/dashboards-monitoring.qmd
- docs/gallery/research-scholarship.qmd
- docs/gallery/teaching-learning.qmd
- docs/gallery/software-documentation.qmd
- docs/gallery/personal-community.qmd
- docs/gallery/browse.qmd

- id: guide
collapse-level: 1
contents:
Expand Down Expand Up @@ -684,8 +697,8 @@ format:
respect-user-color-scheme: true
toc: true
theme:
light: [cosmo, theme.scss]
dark: [cosmo, theme-dark.scss]
light: [cosmo, theme.scss, docs/gallery/assets/_gallery.scss]
dark: [cosmo, theme-dark.scss, docs/gallery/assets/_gallery.scss]
code-copy: true
code-overflow: wrap
css: styles.css
Expand Down
44 changes: 44 additions & 0 deletions _tools/screenshots/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Screenshot and preview tooling

Scripts to capture and update quarto-web's documentation images and gallery media.

There are two families.
Doc screenshots come from `manifest.json` through `capture.js`.
Gallery assets come from `docs/gallery/data/*.yml` through the `scripts/capture-*.mjs` scripts.

Run every command from `_tools/screenshots/`.

## Which tool makes what

| Asset | Command | Script | Output |
| ----------------------------------------- | ----------------------------- | ---------------------------------- | ----------------------------------------------- |
| Doc screenshots (PNG, light and dark) | `npm run capture` | `capture.js` (manifest) | `docs/**/images/*.png` |
| Gallery hover previews (webm and mp4) | `npm run capture:previews` | `scripts/capture-previews.mjs` | `docs/gallery/thumbnails/featured/*.{webm,mp4}` |
| Gallery PDF card thumbnails (PNG) | `npm run capture:pdf-thumbs` | `scripts/capture-pdf-thumbs.mjs` | `docs/gallery/thumbnails/**/*.png` |
| Gallery card thumbnails, image-less (PNG) | `npm run capture:card-thumbs` | `scripts/capture-card-thumbs.mjs` | `docs/gallery/thumbnails/<category>/<slug>.png` |
| axe DevTools console (PNG, manual, macOS) | see script header | `scripts/capture-axe-devtools.mjs` | `docs/output-formats/images/axe-console.png` |

Only `npm run capture:previews` makes the mp4 and webm hover clips.

Each `capture:*` gallery command takes `-- --name <pattern>` to match a subset.
Each also takes `-- --limit <n>` to stage the first `n` matches.

## Prerequisites at a glance

All commands need Node.js 18+ and this tool's dependencies (`npm install`, then `npx playwright install chromium`).

`capture:previews` also needs ffmpeg on `PATH` and a full Playwright Chromium; set `PREVIEW_CHROME` to point at it because the headless shell cannot record video.

`capture:pdf-thumbs` also needs poppler (`pdfinfo`, `pdftoppm`) and ImageMagick (`magick`).

Full setup steps are in `SETUP.md`.
The gallery prerequisites are detailed in `scripts/PREVIEWS.md`.

## Where to read next

`SETUP.md` covers install steps and the still-screenshot workflow.
`scripts/PREVIEWS.md` covers gallery video previews plus PDF and card thumbnails in detail.
`docs/gallery/README.md` covers how to add the gallery entries these thumbnails serve.
`CLAUDE.md` covers the AI-assisted workflow and the `manifest.json` field reference.
`DECISIONS.md` covers why the tooling is built the way it is.
`npm run help` prints the full command list.
6 changes: 6 additions & 0 deletions _tools/screenshots/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ playwright-cli -s=screenshot screenshot --filename=docs/websites/images/about-jo
playwright-cli -s=screenshot close
```

## Gallery featured video previews

`scripts/capture-previews.mjs` (`npm run capture:previews`) records the animated preview
clips for featured gallery cards. It is separate from the still-screenshot manifest and
needs ffmpeg plus a full Playwright Chromium. See **`scripts/PREVIEWS.md`** for details.

## Optional: PNG Compression

```bash
Expand Down
29 changes: 29 additions & 0 deletions _tools/screenshots/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions _tools/screenshots/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@
"serve": "node scripts/serve.js",
"compress": "node scripts/compress.js",
"capture": "node capture.js",
"capture:previews": "node scripts/capture-previews.mjs",
"capture:pdf-thumbs": "node scripts/capture-pdf-thumbs.mjs",
"capture:card-thumbs": "node scripts/capture-card-thumbs.mjs",
"open": "node scripts/open.js",
"validate": "node scripts/validate.js",
"update-demo": "bash scripts/update-demo.sh"
},
"dependencies": {
"ajv": "^8.18.0",
"js-yaml": "^5.2.3",
"open": "^10.0.0",
"playwright": "^1.50.0",
"sharp": "^0.33.0"
},
"allowScripts": {
"sharp@0.33.5": true
}
}
88 changes: 88 additions & 0 deletions _tools/screenshots/scripts/PREVIEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Gallery featured video previews

`capture-previews.mjs` generates the short, muted, looping clips that featured
gallery cards play on hover or keyboard focus. The rendering,
interaction, and reduced-motion handling live in the gallery, not here:
`docs/gallery/assets/_featured.ejs.md` and `docs/gallery/assets/_gallery.scss`.

This script is separate from the still-screenshot manifest (`capture.js`): it
records motion rather than a single frame, and is driven by gallery data rather
than `manifest.json`.

## How it works

- Driven by `docs/gallery/data/featured.yml`: every card with both a `live` URL
and a `preview` base path gets a clip. `preview:` is the output path without
extension, e.g. `thumbnails/featured/software-documentation-gribouille`.
- Optional `preview-url:` overrides the page that is recorded when the card's
`live` link is not the best source (e.g. a landing page vs a richer subpage). The
card's `live` link is unchanged; only the capture source differs.
- Output: `<preview>.webm` (VP9) and `<preview>.mp4` (H.264) under
`docs/gallery/thumbnails/featured/` (animated previews are a featured-only
asset), beside the still PNG (`image:`), which stays the `<video>` poster.
- Capture mode comes from the card's `categories`:
- **reveal.js** (`revealjs`/`presentation`) → step through a few slides with
ArrowRight.
- **everything else** → scroll the page top to bottom.
- The blank page-load lead-in is measured and trimmed from the encode, so clips
open on real content and loop without a white flash.
- Each file is size-budgeted; the script warns above 500 KB.

Cards without a `preview:` field keep the static PNG. Leave it off for pages that
do not benefit: single-screen dashboards, PDF/blob `live` URLs, or sites that block
headless capture.

## Prerequisites

- **ffmpeg** on `PATH` (`brew install ffmpeg`). Playwright records VP8 webm only;
ffmpeg re-encodes to a smaller VP9 webm and an H.264 mp4 for Safari/broad support.
- **A full Playwright Chromium** — the headless shell cannot record video. The
script defaults to the installed `chromium-*/chrome-mac-arm64` build; set
`PREVIEW_CHROME` to override the path (`npx playwright install chromium`).
- **This tool's dependencies installed** — `npm install` in `_tools/screenshots`
(the script uses the tool's `playwright` and `js-yaml`).

## Usage

From `_tools/screenshots`:

```bash
npm run capture:previews # every preview card
npm run capture:previews -- --name whr # match by name or preview path
npm run capture:previews -- --limit 2 # first N matches (staging)
```

After capturing, re-render the landing (`quarto render docs/gallery/index.qmd`) and
check the clips in the browser in both themes.

# PDF card thumbnails

`capture-pdf-thumbs.mjs` builds the still `image` for cards whose `live` URL is a
PDF, rendering the PDF's first two pages (or the first page alone when it has only
one) into a side-by-side spread that overwrites the card's existing thumbnail.

- Driven by `docs/gallery/data/*.yml`: every card with a `.pdf` `live` URL. GitHub
`blob` URLs are rewritten to `raw.githubusercontent.com` before download.
- Output: overwrites the card's `image` PNG under `docs/gallery/thumbnails/`.
- Prerequisites: **poppler** (`pdfinfo`, `pdftoppm`) and **ImageMagick** (`magick`)
on `PATH` (`brew install poppler imagemagick`).

```bash
npm run capture:pdf-thumbs # every PDF-linked card
npm run capture:pdf-thumbs -- --name whr # match by name or image path
npm run capture:pdf-thumbs -- --limit 1 # first N matches (staging)
```

# Card thumbnails for image-less entries

`capture-card-thumbs.mjs` fills the `image` for cards that have none yet and whose
`live` URL is a normal web page (PDF-linked cards go through `capture-pdf-thumbs.mjs`).
It screenshots the page top to `docs/gallery/thumbnails/<category>/<slug>.png`,
dismissing a cookie/consent banner first, then prints the `image:` and a placeholder
`alt:` line to add to the card (it does not edit the YAML).

```bash
npm run capture:card-thumbs # every image-less web card
npm run capture:card-thumbs -- --name rap # match by name
npm run capture:card-thumbs -- --limit 1 # first N matches (staging)
```
Loading
Loading