vps: forgejo README renderer doesn't expand github user-attachments video URLs #16

Closed
opened 2026-05-01 19:32:26 +00:00 by barrettruth · 0 comments
Owner

Symptom

Markdown like:

https://github.com/user-attachments/assets/99ba05f6-9dbf-4645-8491-cf10af208743

renders correctly on github.com as an embedded <video controls> element (auto-play, loop, inline-playable). Live example: https://github.com/barrettruth/vimdoc-language-server shows the playable video.

On our forgejo self-host (git.barrettruth.com), the same URL in the same README renders as a plain hyperlink:

<p dir="auto"><a href="https://github.com/user-attachments/assets/99ba05f6-9dbf-4645-8491-cf10af208743" rel="nofollow">https://github.com/user-attachments/assets/99ba05f6-9dbf-4645-8491-cf10af208743</a></p>

Live example: https://git.barrettruth.com/barrettruth/vimdoc-language-server shows the URL as text.

Why this matters

We just rolled out the v2 deprecate-to-forgejo mirror pattern (forgejo canonical, github passive mirror). For canonical READMEs to be useful on the forgejo side, embeds that work on github MUST work on forgejo too. Otherwise a visitor landing at the canonical home gets a degraded experience compared to the mirror, which inverts the intended hierarchy.

vimdoc-language-server is the prototype affected today — its README opens with a demo video. Any other repo that uses this idiom (and several upstream barrettruth/* repos do) will hit the same gap.

Root cause hypothesis

Github's renderer special-cases the https://github.com/user-attachments/assets/<uuid> URL pattern: it detects the redirect Content-Type from objects.githubusercontent.com (video/mp4, image/png, etc.) and emits <video> / <img> accordingly. Forgejo's markdown renderer doesn't have this special case — bare URLs become anchor tags.

Three possible fix paths to investigate:

  1. Upstream forgejo PR — add github-user-attachments handling to forgejo's markdown renderer. Slow, depends on upstream review.
  2. Local forgejo patch via pkgs/forgejo-cm6-langs/ (or a sibling pkgs override) — same pattern we used for the cm6 syntax recoloring. Patch the renderer to detect ^https?://github.com/user-attachments/assets/.+$ bare URLs on their own paragraph and emit <video src="..." controls autoplay loop muted playsinline>. Or use a sniff probe: HEAD the URL, follow the redirect to objects.githubusercontent.com, read Content-Type, choose tag accordingly.
  3. Markdown post-processor at the templates layer — Forgejo allows custom/templates/ overrides. We could add a tiny client-side script that finds <a> whose href matches the user-attachments pattern and replaces with <video>. Less invasive than patching forgejo source but client-side only (won't help raw markdown view, RSS, etc.).

Option 2 is the most consistent with the existing pkgs override pattern (pkgs/forgejo-cm6-langs/) but needs research into where in forgejo's source the bare-URL-to-anchor transformation happens. Likely modules/markup/markdown/... or modules/markup/sanitizer.go.

Auto-play behavior (sub-question)

Github's emitted <video> element has autoplay loop muted playsinline attributes. Whether the forgejo override should match (auto-play) or differ (require click-to-play) is a separate decision. Default to matching github (auto-play, muted, loop) for visual parity unless a strong reason emerges to differ.

Acceptance criteria

  • Visiting https://git.barrettruth.com/barrettruth/vimdoc-language-server shows the demo video inline, not a hyperlink.
  • The same renderer change applies repo-wide: any future barrettruth/* repo with a https://github.com/user-attachments/assets/<uuid> URL on its own paragraph renders as a video.
  • Image-flavored github user-attachments URLs (PNG/JPG) also render as <img> — same special-case logic, different content-type branch.
  • Mobile rendering works (no autoplay-without-mute breakage in Safari).

Out of scope

  • Backporting to old forgejo versions — we run latest, this is a one-host fix.
  • Self-hosting the actual asset blobs — github's CDN URLs are stable, we just need the renderer to honor them.
## Symptom Markdown like: ``` https://github.com/user-attachments/assets/99ba05f6-9dbf-4645-8491-cf10af208743 ``` renders correctly on github.com as an embedded `<video controls>` element (auto-play, loop, inline-playable). Live example: <https://github.com/barrettruth/vimdoc-language-server> shows the playable video. On our forgejo self-host (`git.barrettruth.com`), the same URL in the same README renders as a plain hyperlink: ```html <p dir="auto"><a href="https://github.com/user-attachments/assets/99ba05f6-9dbf-4645-8491-cf10af208743" rel="nofollow">https://github.com/user-attachments/assets/99ba05f6-9dbf-4645-8491-cf10af208743</a></p> ``` Live example: <https://git.barrettruth.com/barrettruth/vimdoc-language-server> shows the URL as text. ## Why this matters We just rolled out the v2 `deprecate-to-forgejo` mirror pattern (forgejo canonical, github passive mirror). For canonical READMEs to be useful on the forgejo side, embeds that work on github MUST work on forgejo too. Otherwise a visitor landing at the canonical home gets a degraded experience compared to the mirror, which inverts the intended hierarchy. `vimdoc-language-server` is the prototype affected today — its README opens with a demo video. Any other repo that uses this idiom (and several upstream `barrettruth/*` repos do) will hit the same gap. ## Root cause hypothesis Github's renderer special-cases the `https://github.com/user-attachments/assets/<uuid>` URL pattern: it detects the redirect Content-Type from `objects.githubusercontent.com` (`video/mp4`, `image/png`, etc.) and emits `<video>` / `<img>` accordingly. Forgejo's markdown renderer doesn't have this special case — bare URLs become anchor tags. Three possible fix paths to investigate: 1. **Upstream forgejo PR** — add github-user-attachments handling to forgejo's markdown renderer. Slow, depends on upstream review. 2. **Local forgejo patch via `pkgs/forgejo-cm6-langs/` (or a sibling pkgs override)** — same pattern we used for the cm6 syntax recoloring. Patch the renderer to detect `^https?://github.com/user-attachments/assets/.+$` bare URLs on their own paragraph and emit `<video src="..." controls autoplay loop muted playsinline>`. Or use a sniff probe: HEAD the URL, follow the redirect to `objects.githubusercontent.com`, read Content-Type, choose tag accordingly. 3. **Markdown post-processor at the templates layer** — Forgejo allows `custom/templates/` overrides. We could add a tiny client-side script that finds `<a>` whose `href` matches the user-attachments pattern and replaces with `<video>`. Less invasive than patching forgejo source but client-side only (won't help raw markdown view, RSS, etc.). Option 2 is the most consistent with the existing pkgs override pattern (`pkgs/forgejo-cm6-langs/`) but needs research into where in forgejo's source the bare-URL-to-anchor transformation happens. Likely `modules/markup/markdown/...` or `modules/markup/sanitizer.go`. ## Auto-play behavior (sub-question) Github's emitted `<video>` element has `autoplay loop muted playsinline` attributes. Whether the forgejo override should match (auto-play) or differ (require click-to-play) is a separate decision. Default to matching github (auto-play, muted, loop) for visual parity unless a strong reason emerges to differ. ## Acceptance criteria - Visiting `https://git.barrettruth.com/barrettruth/vimdoc-language-server` shows the demo video inline, not a hyperlink. - The same renderer change applies repo-wide: any future `barrettruth/*` repo with a `https://github.com/user-attachments/assets/<uuid>` URL on its own paragraph renders as a video. - Image-flavored github user-attachments URLs (PNG/JPG) also render as `<img>` — same special-case logic, different content-type branch. - Mobile rendering works (no autoplay-without-mute breakage in Safari). ## Out of scope - Backporting to old forgejo versions — we run latest, this is a one-host fix. - Self-hosting the actual asset blobs — github's CDN URLs are stable, we just need the renderer to honor them.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
barrettruth/nix#16
No description provided.