Skip to content

fix(viewer): clip slide viewport to current slide boundaries#34

Merged
bahdotsh merged 2 commits into
mainfrom
fix/slide-mode-content-bleed
Mar 29, 2026
Merged

fix(viewer): clip slide viewport to current slide boundaries#34
bahdotsh merged 2 commits into
mainfrom
fix/slide-mode-content-bleed

Conversation

@bahdotsh
Copy link
Copy Markdown
Owner

@bahdotsh bahdotsh commented Mar 29, 2026

Summary

  • Fixes slide mode rendering content from subsequent slides beyond the current slide's boundary (BUG: Slide mode renders content from subsequent slides #30)
  • Computes slide_end from slide_boundaries[current_slide + 1] and gates all wrapped.get() calls with .filter(|_| line_idx < slide_end) so lines past the boundary fall through to the existing blank-row path
  • Applies the same guard to both image rendering passes (inline and block) to prevent images bleeding across slides
  • Removes the unused _display_lines/_display_offset variables that had a partial, never-wired-up version of this fix

Test plan

  • Create a markdown file with --- separators (3+ slides with varying content lengths)
  • Run mdterm --slides file.md and verify each slide only shows its own content
  • Verify slide navigation (arrow keys, space, h/l/j/k) still works correctly
  • Verify status bar still shows correct "Slide X/Y" indicator
  • Verify slides with images don't bleed image content across boundaries
  • cargo test passes (120/120)
  • cargo clippy and cargo fmt --check clean

Closes #30

The slide mode rendering loop computes slide_start just fine, but
then *never* computes slide_end. So wrapped.get(line_idx) happily
returns content from the next slide whenever the current slide has
fewer lines than the viewport height.

The status bar correctly shows "Slide 1/3" while you're staring at
content from slides 1, 2, and 3 all at once. Not great.

It turns out there was already a slide_end computation sitting right
there in render_frame — stored in _display_lines and _display_offset
— except those variables were never actually *used*. Presumably
someone started the fix and forgot to finish it.

Hoist slide_end before the row loop and gate every wrapped.get()
call with .filter(|_| line_idx < slide_end). Lines past the boundary
now return None, which falls through to the existing blank-row path.
Same guard applied to the image rendering passes so images don't
bleed across slides either.

Closes #30
The previous commit introduced slide_end to stop content from
bleeding across slide boundaries, but it left slide_start computed
*four separate times* inside render_frame — once per row, every
single frame. That's not a bug, but it's the kind of copy-paste
that breeds bugs.

Hoist both slide_start and slide_end into a single (start, end)
pair at the top of render_frame. In non-slide mode slide_start is
just state.offset, so the arithmetic stays identical. The four
inline boundary lookups collapse into `slide_start + row`.

While at it, link_at_position() was *not* guarded by slide_end at
all. Click on a visually blank row past the current slide's content
and it would happily resolve a link from the next slide. Guard it
the same way: compute slide_end locally and bail early if the index
is out of bounds.

Net result: fewer lines, one less place to get wrong, and clicking
on blank space no longer activates ghost links.
@bahdotsh bahdotsh merged commit 2802f0f into main Mar 29, 2026
5 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.

BUG: Slide mode renders content from subsequent slides

1 participant