Skip to content

fix(viewer): keep Markdown rendered when opened in a new tab - #823

Merged
devswha merged 3 commits into
mainfrom
fix/markdown-new-tab
Oct 11, 2026
Merged

devswha merged 3 commits into
mainfrom
fix/markdown-new-tab

Conversation

@devswha

@devswha devswha commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Change

Markdown already renders inside the file viewer after #616, but Open in a new tab still points at /api/fs/file and displays the source. Open .md and .markdown files through the app's existing renderer in the new tab instead.

  • Link to the resolved absolute file on its owning PC, without depending on the original pane.
  • Honor the linked PC over the browser's stored selection, preserve the file through automatic pane selection and reload, and never read a local file when the linked PC is unknown.
  • Add a separate Open raw file action. The raw API, downloads, non-Markdown files and preview size limit retain their existing behavior.
  • Include Korean, Japanese and Chinese labels, design documentation and a changelog entry.

Related to #510 and #429. This addresses the new-tab Markdown gap, not the remaining code-viewer settings and line-number proposals.

Validation

  • bun run typecheck: passed.
  • Production build: passed.
  • TMPDIR=/tmp HERDR_TEST_MODE=unit bun test ./src/lib/deepLink.test.ts ./src/lib/markdownImages.test.ts ./src/lib/filePreviewText.test.ts ./src/lib/i18n.test.ts: 43 passed, 0 failed.
  • TMPDIR=/tmp CHROME_PATH=<Chromium> UI_EVIDENCE_DIR=<evidence-dir> bun run check run --build bun scripts/file-viewer-regression.ts: passed against an isolated herdr and the real file server.
    • In-app and new-tab rendering at 390px and 1440px, dark and light.
    • Headings, tables, task lists, code and relative local images.
    • Reload, close/history behavior, Unicode and reserved characters in the file path.
    • Raw and downloaded content match the original bytes.
    • Remote PC with no panes and a different stored selection; local PC with a stored remote selection; unknown PC with no file reads. The remote bridge hop is a fixture; stat and file reads use the real server.
  • Read-only final code review: no remaining blocker.

bun run check fast did not fully pass on this macOS/Bun 1.4.0 host. The unrelated existing failures were:

  • scripts/check.test.ts: temporary Unix socket path is 120 characters, over the 100-character limit.
  • server/voice.test.ts:229: expected multipart filename audio.webm, received clip.webm.

Eight screenshots were captured and inspected from the owned test session at node_modules/.cache/markdown-evidence/markdown-{inline,tab}-{390,1440}-{dark,light}.png. They are not attached here because the authenticated browser attachment tool was unavailable. The command above regenerates them; no screenshots or machine-local evidence files are committed.

Release

Client-side change; no HTTP/WS contract or remote runtime bundle change. Installed users need an app release containing this PR. Existing direct /api/fs/file URLs intentionally remain raw-file URLs.

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 12 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: devswha/herdr-web-ui/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2d1f0ec4-60f3-4bfc-b54e-51b95f78a3f3

📥 Commits

Reviewing files that changed from the base of the PR and between 6e6eaaf and c392427.


📒 Files selected for processing (11)
  • CHANGELOG.md
  • DESIGN.md
  • scripts/file-viewer-regression.ts
  • src/App.tsx
  • src/components/FileViewer.tsx
  • src/lib/deepLink.test.ts
  • src/lib/deepLink.ts
  • src/lib/i18n.ja.ts
  • src/lib/i18n.ko.ts
  • src/lib/i18n.tr.ts
  • src/lib/i18n.zh.ts

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@devswha
devswha merged commit 4cf5b96 into main Oct 11, 2026
9 checks passed
@devswha
devswha deleted the fix/markdown-new-tab branch October 11, 2026 17:40
devswha added a commit that referenced this pull request Oct 11, 2026
## Change

The pull request template and `CONTRIBUTING.md` asked every UI change to
attach a screenshot or recording. The maintainer does not review from
those images, and a PR opened from the command line cannot attach one,
so recent PRs (#823, #824) carried a note saying the images were
captured but not attached. Remove the requirement from both places.

Unchanged: the rules about where a capture comes from when someone does
make one (`AGENTS.md` and `CONTRIBUTING.md`: a demo or test session,
never a live one).

## Validation

Documentation only. `git diff` touches one sentence in
`.github/pull_request_template.md` and one in `CONTRIBUTING.md`; a
search of `.github`, `CONTRIBUTING.md`, the `AGENTS.md` files and
`docs/development.md` found no other place that asks for an attachment.

## Release

No app or runtime change.
devswha added a commit that referenced this pull request Oct 11, 2026
…cument (#849)

## Problem
From mobile/desktop testing of 0.4.7: **Open in a new tab** on a
markdown file (#823) opened a second full copy of the app (sidebar,
panes, chat, its own PC connections) with the file viewer as a modal
over it. Closing the viewer left the tab as just another app window.

## Change
- `src/lib/fileReader.ts`: `readerHref(machine, path)` →
`?read=<path>&machine=<id>`, `readerFromSearch`, and
`resolveFromDocument` (a link resolved from the document's folder).
- `src/main.tsx`: a `?read=` address renders `<FileReader>` instead of
`<App>` (still inside `SettingsProvider`, so theme/palette/language
apply). Auth is the same cookie the app uses.
- `FileReader`: `MachineContext` from the address, `FileViewer` in
`page` mode, `document.title` = file name; links to other files push a
new `?read=` entry and Back returns (popstate).
- `FileViewer` `page` prop: a `<main>` instead of the modal; no focus
trap, swipe-down, Escape or close button; header keeps name, size, path,
**Open raw file** and **Download** (no "Open in a new tab" — it is the
tab). The modal's "Open in a new tab" for markdown now points at
`readerHref`.
- `?file=` links (deep links, the address while the in-app viewer is
open) are unchanged: they still open the app with the viewer.

## Tests
- Unit: `fileReader.test.ts` (address round trip, `?file=` is not a
reader address, relative/absolute/`~`/`..` resolution).
- `file-viewer-regression`: the new tab is a `.file-reader` with a
`read=` address, no sidebar/terminal/modal, no close or new-tab control,
the file name as title; raw/download/reload as before; a relative link
in the document opens `other.md` in the reader and Back returns. PC
ownership: the reader link from a remote-fixture file reads only through
`/api/machines/remote-fixture/fs/`, and a reader address for a PC not
set up here never reads `/api/fs/`.
- `bun run check fast` passes. Screenshots at 390 and 1440, dark and
light, checked.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant