fix(response-viewer): keep a path link's label in the prose font, pin its edges

Merge-time fix for #665.

- A markdown link converted to a preview link became `a.rv-path`, so its
  label ("Our incident record") took the path style: monospace, 0.92em
  and `word-break: break-all`, which split prose mid-word on a phone. The
  anchor now also carries `rv-path-link`, and
  `.rv-text a.rv-path.rv-path-link` resets font and word-break, as the
  File Viewer does for its labelled document links.
- The first new test adds `/tmp/a.json?raw=true` (pins the `?query`
  strip) and `/tmp/` (pins the trailing-slash folder check, since
  findFilePathLinks finds no folder in a bare `/tmp/`), and checks the
  new class.
- The `_linkifyFilePaths` JSDoc and docs/architecture-invariants.md say
  the function also rewrites anchors whose href is a scheme-less,
  non-`//` path, on purpose without FILE_PATH_LINK_PATTERN's root and
  extension filter.
- Mobile Guide: "a web link" in the response viewer opens a tab.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-10-22 19:20:01 +02:00
1 parent 6f785e116f
commit fde23e3a07
5 files changed
+28 -5

No files matched your search

+9 -1
View File
@@ -2959,6 +2959,12 @@ class CodemanApp {
* output. Subtrees already inside an `<a>` are skipped so an autolinked URL
* is never re-cut, and the anchor's textContent is the path verbatim, so
* "copy code" still yields exactly what the agent printed.
*
* Before that walk it also rewrites an existing anchor whose href is a path
* (no scheme, not `//host`, not a bare `#fragment`) into the same `a.rv-path`
* shape, on purpose WITHOUT `FILE_PATH_LINK_PATTERN`'s root and extension
* filter: the agent chose that href as a link target, and left alone it opens
* as a same-origin URL (a 404 page in a new tab).
*/
_linkifyFilePaths(root) {
if (!root || typeof document === 'undefined') return;
@@ -2984,7 +2990,9 @@ class CodemanApp {
}
// A bare `#fragment` (and every `.rv-path`, whose href is `#`) ends up empty.
if (!path) continue;
a.className = 'rv-path';
// rv-path-link keeps the label in the prose font (styles.css): it is a label,
// not a path, and break-all would split it mid-word on a phone.
a.className = 'rv-path rv-path-link';
a.dataset.path = path;
a.dataset.linkified = '1';
if (path.endsWith('/') || findFilePathLinks(path).some((f) => f.folder && f.path === path)) a.dataset.folder = '1';
+8
View File
@@ -14926,6 +14926,14 @@ html:is([data-skin="paper-gray"], [data-skin="solarized-light"], [data-skin="cat
cursor: pointer;
}
/* A markdown link whose target is a path (`[Our incident record](/tmp/x.json)`)
takes the rv-path shape for the click delegate, but its text is a label, not a
path: keep it in the prose font and never break it mid-word. */
.rv-text a.rv-path.rv-path-link {
font: inherit;
word-break: normal;
}
/* Tables — scroll wrapper keeps table proper while allowing horizontal overflow */
.rv-table-wrap {
margin: 1em 0;