Skip to content

feat(files): render Markdown previews with a centered outline - #651

Closed
od-studio-webagency wants to merge 1 commit into
devswha:mainfrom
od-studio-webagency:feat/markdown-preview-outline
Closed

od-studio-webagency wants to merge 1 commit into
devswha:mainfrom
od-studio-webagency:feat/markdown-preview-outline

Conversation

@od-studio-webagency

@od-studio-webagency od-studio-webagency commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Change

Closes #636

  • Markdown 렌더링/원본 전환, 문서 기준 상대 링크, 원문 다운로드와 접힌 속성 영역을 제공합니다.
  • 제목 수준과 중복 제목을 보존하는 목차가 본문을 따라 중앙으로 이동하며 포커스·본문 위치를 건드리지 않습니다.
  • 기존 앱 테마, 글자 크기, 모바일 safe area와 포커스 트랩을 유지합니다.

#510, #429, #616과 겹치는 미리보기 논의를 연결합니다. 이 초안의 추가 제안은 목차와 읽기 위치 탐색이며, Mermaid나 새 구문 강조 의존성을 넣지 않았습니다.

Validation

generate:types --check, typecheck, build, test:unit 통과. 새 preview/TOC 회귀는 1440/390px 밝은·어두운 테마에서 통과했습니다. 기존 파일 열기/뒤로·앞으로/Settings·Add PC 포커스 검사와 모바일 미디어 16개 경우도 통과했습니다.

모든 검증은 별도 작업 공간과 소유한 테스트/demo 환경에서 수행했습니다. 사용자의 실행 중 앱·terminal은 변경하지 않았습니다.

화면 증거

개인 대화나 사용자 세션이 아닌, 소유한 테스트/demo 환경의 가상 데이터로 촬영했습니다.

markdown-desktop

@coderabbitai

coderabbitai Bot commented Oct 9, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@devswha

devswha commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Thanks for this. Markdown previews in the file viewer are already under review in #429, which the maintainer has reviewed several times (#669, #670 and #671 were split out of it and have landed), and #616 covers the same ground with images. Closing this as a duplicate to keep the work in one place. If the centered outline is something you'd like to propose on top, please open an issue for it once a preview has landed.

@devswha devswha closed this Oct 11, 2026
devswha added a commit that referenced this pull request Nov 5, 2026
Fixes #636.

## What

A new opt-in setting, **Settings > File viewer > Markdown outline** (off
by default, a device setting in its own storage key like the other
recent opt-ins). With it on, a Markdown Preview that has two headings or
more lists them:

- **Levels and repeated titles.** The outline lists the document's own
headings (not ones inside a quote), each level under the shallowest one
stepped in. A title written twice is two entries, and each goes to its
own heading.
- **Follows the reading.** As the document scrolls, the heading being
read (the last one past a line 32 px under the body's top) is marked
with the accent on a tint, and kept in the middle of the list. Only the
list scrolls to do that, so the browser clamps it at the list's start
and end, and the document's position and the keyboard focus never move
with it. At the very end of the document, the last heading in view is
marked (short final sections cannot reach the reading line).
- **Choosing an entry** brings its heading to 8 px under the top. A
chosen entry stays marked while the document rests where the choice left
it, even when the end of the document keeps the heading from reaching
the top.
- **Wide viewer** (body at least 760 px: the popup and the reader tab on
a desktop): a 240 px column after the document. The header's new
**Outline** button folds and unfolds it.
- **Narrow viewer** (a phone, the docked panel): nothing changes until
the **Outline** button (header; the toolbar when docked) is pressed. It
opens the outline as a drawer over the document's end edge, so the text
keeps its whole width. Opening the drawer centers the heading being read
and puts the focus on it. A choice, Escape (which closes the drawer
only, not the viewer) or a press outside closes it, and the focus
returns to the button.

With the setting off (the default), the viewer is unchanged: the body's
new wrapper is `display: contents`, so it lays nothing out. The wrapper
is always rendered so the body is never remounted when an outline
appears, which keeps its focus and scroll.

**Design reference:** Zed's outline panel (the current symbol is marked
and kept in view while the editor scrolls) for the column, and GitHub's
Markdown file outline button for the narrow drawer. There is a DESIGN.md
entry.

Compared with #651 (closed as a duplicate before the Markdown preview
landed): this builds on the preview that is on main now, adds only the
outline, and keeps it opt-in.

## Tests

- `scripts/markdown-outline-browser-qa.ts` (new, added to
`scripts/ci-browser.sh`): the real viewer built by Vite and served under
the app's CSP, light and dark.
- Off: no outline, no button, and the wrapper computes to `display:
contents`.
- 1280 popup: a column whose width plus the body's equals the row; 61
entries for 61 headings; depth classes for `#`/`##`/`###`; the first
entry marked at the start with the list at scrollTop 0; scrolling to
Section 16 marks it within 2 px of the list's center while the body's
scrollTop and `document.activeElement` stay unchanged; at the end the
list is at its own end; the third "Notes" entry lands the third Notes
heading at 8 px; choosing Section 30 near the end keeps it marked; the
button folds and restores the column.
- 390 phone: no column until the button; the drawer does not change the
body's width; opening centers and focuses Section 21; Escape closes only
the drawer and returns focus to the button; a choice scrolls to the
heading, closes, and returns focus; a tap on the document closes it.
- Narrow, after review: a dialog in front of the viewer (Settings) keeps
its Escape and focus while the drawer stays open; a touch stroke down
the drawer at its top does not drag the viewer's sheet.
- Docked at 1280: the toolbar's Outline button opens a drawer over the
panel, and the pane beside it keeps its Escape and focus.
- **Failing first:** with `src/` at origin/main the script fails at its
first step (no wrapper, no outline).
- `src/lib/markdownOutline.test.ts`: the entry list (levels, words with
formatting dropped, quoted headings left out, repeated titles as
separate places, wordless headings skipped) and the current-heading
rule.
- `src/lib/settings.test.ts`: the default, sanitising and device scope,
and the setting's own key surviving an old tab's whole-record save.

## Screenshots

Fixture data (no user session), 1280x800 and 390x844, dark and light;
checked by eye: the column and the drawer, the marked entry centered,
the indent per level, and the Outline button's on state.

## Validation

- `bun run check fast`: pass on the merged head 57863e2 (workflow
syntax, generated types/themes, typecheck, build, 12364 unit tests, 0
failures).
- `bun scripts/markdown-outline-browser-qa.ts`: pass, also on the merged
head (with `files-prompt-regression`, whose #3053 Escape steps landed
meanwhile).
- Sheet-drag regressions after the review fix (`src/lib/sheets.ts`), in
`herdr-ci-runner:local`: `key-bar-customization-demo-regression`,
`link-menu-demo-regression`, `phone-worktree-sheet-regression`: all
PASS.
- Browser regressions covering FileViewer, run in
`herdr-ci-runner:local`: all pass: `markdown-outline-browser-qa`,
`file-viewer-regression` (79 PASS), `file-viewer-mobile-regression`,
`file-preview-text-browser-qa`, `virtual-source-browser-qa`,
`files-panel-demo-regression`, `file-text-size-demo-regression`,
`settings-pages-demo-regression`, `deep-link-demo-regression`,
`render-crash-demo-regression`, `web-panel-mobile-regression`,
`repo-diff-browser-qa`, `relay-media-browser-qa`,
`link-menu-demo-regression`, and `files-prompt-regression` (through `bun
run check run`, 8 PASS).
- Not run: the full browser suite (CI runs it), and native iOS/Android
or Windows checks.
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.

feat(files): add a centered outline to rendered Markdown previews

2 participants