feat(markdown): spoiler text - ||text|| renders click-to-reveal (LC-290) #323

Merged
longjacksonle merged 1 commit from feat/lc-290-spoiler-markdown into main 2026-06-14 20:37:53 +02:00

Summary

Adds Discord/GitHub-style spoiler markdown. ||text|| renders as a filled box whose content is hidden until the reader reveals it by clicking it (or focusing it and pressing Enter/Space). Reveal is one-way per element.

Changes

  • server/src/views/markdown.rs: render_with_spoilers runs on non-code, non-link text runs and wraps each ||...|| pair as <span class="lc-spoiler" data-lc-spoiler tabindex="0"><span class="lc-spoiler-inner">...</span></span>. Inner text and surrounding segments still flow through the math/mention/emoji/link pipeline. || inside inline code or code blocks stays literal (code never reaches the text branch). An unterminated || is emitted literally. A no-|| fast path keeps untouched bodies byte-identical (LC-77 golden fixtures unchanged).
  • server/assets/main.css: .lc-spoiler filled box (recolors with the active theme), .lc-spoiler-inner transparent until .lc-spoiler-revealed.
  • server/templates/layout.html: one delegated reveal handler (click + Enter/Space), so spoilers in live-appended messages work without re-binding.

No locale text is baked into the span, keeping the content-keyed markdown cache correct across locales.

Testing

  • just check, just fmt, just test, just test-saas all pass.
  • New unit tests: spoiler renders; || in inline code stays literal; unterminated || stays literal.
  • No LC-77 fixture diff (fixture bodies contain no ||).

Not operator-visible (no env/config/contract change).

## Summary Adds Discord/GitHub-style spoiler markdown. `||text||` renders as a filled box whose content is hidden until the reader reveals it by clicking it (or focusing it and pressing Enter/Space). Reveal is one-way per element. ## Changes - `server/src/views/markdown.rs`: `render_with_spoilers` runs on non-code, non-link text runs and wraps each `||...||` pair as `<span class="lc-spoiler" data-lc-spoiler tabindex="0"><span class="lc-spoiler-inner">...</span></span>`. Inner text and surrounding segments still flow through the math/mention/emoji/link pipeline. `||` inside inline code or code blocks stays literal (code never reaches the text branch). An unterminated `||` is emitted literally. A no-`||` fast path keeps untouched bodies byte-identical (LC-77 golden fixtures unchanged). - `server/assets/main.css`: `.lc-spoiler` filled box (recolors with the active theme), `.lc-spoiler-inner` transparent until `.lc-spoiler-revealed`. - `server/templates/layout.html`: one delegated reveal handler (click + Enter/Space), so spoilers in live-appended messages work without re-binding. No locale text is baked into the span, keeping the content-keyed markdown cache correct across locales. ## Testing - `just check`, `just fmt`, `just test`, `just test-saas` all pass. - New unit tests: spoiler renders; `||` in inline code stays literal; unterminated `||` stays literal. - No LC-77 fixture diff (fixture bodies contain no `||`). Not operator-visible (no env/config/contract change).
feat(markdown): spoiler text - ||text|| renders click-to-reveal (LC-290)
All checks were successful
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Kingfisher (pull_request) Successful in 7s
Create release / Create release from merged PR (pull_request) Has been skipped
check-secrets / Nosey parker (pull_request) Successful in 4s
check-secrets / TruffleHog (pull_request) Successful in 5s
Check / clippy + fmt + tests (pull_request) Successful in 3m54s
a88e50e7eb
Add a spoiler pass to the markdown renderer so `||text||` renders as a filled box whose content is hidden until the reader clicks it (or focuses it and presses Enter/Space). Mirrors the Discord/GitHub spoiler convention.

The pass runs only on non-code, non-link text runs (`render_with_spoilers` in views/markdown.rs), so `||` inside inline code or code blocks stays literal. Each spoiler's inner text and the surrounding segments still flow through the normal math/mention/emoji/link pipeline, so formatting works inside and around a spoiler. An unterminated `||` is emitted literally. A no-`||` fast path keeps untouched bodies (and the LC-77 golden fixtures) byte-identical.

Reveal is a single delegated handler in layout.html (click + Enter/Space), one-way per element, so spoilers in live-appended messages work without re-binding. No locale-dependent text is baked into the span, keeping the content-keyed markdown cache correct across locales.

#LC-290
#LC-291

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch feat/lc-290-spoiler-markdown 2026-06-14 20:37:53 +02:00
Sign in to join this conversation.
No reviewers
No labels
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
psa-systems/lets-chat!323
No description provided.