Code section: render directory markdown files as tabs (README first) #170

Closed
opened 2026-09-06 00:33:45 +00:00 by crueber · 3 comments
Owner

Code section: render directory markdown files as tabs (README first)

In the code section (Tree view), below the file list, automatically render the directory's markdown files — each as a tab. README.md (case-insensitive match: readme.md/README.MD/etc.) is always the first tab and shows by default; the rest follow in alphabetical order (by filename).

Scope decisions for the implementer

  • Source set: *.md/*.markdown files in the CURRENT directory listing (not recursive; subdirectories' docs stay one click away). Render the section only when ≥1 markdown file exists.
  • Tab switching is client-side state (no route change required, but deep-linkable # anchor is a plus if cheap); content rendered through the existing markdown-lite + sanitizer pipeline (same as blob MD preview).
  • Large files: reuse the blob too_large cap behavior (don't render megabytes of markdown).
  • Filenames with special characters must not break tabs or anchors.

Acceptance criteria

  • README first + alphabetical rest, per-directory; section hidden when no markdown files.
  • node --test green; browser check (dir with README + several .md, dir with none, case variants) both themes, zero console errors; no new deps.
# Code section: render directory markdown files as tabs (README first) In the code section (Tree view), below the file list, automatically render the directory's markdown files — each as a tab. `README.md` (case-insensitive match: `readme.md`/`README.MD`/etc.) is always the first tab and shows by default; the rest follow in alphabetical order (by filename). ## Scope decisions for the implementer - Source set: `*.md`/`*.markdown` files in the CURRENT directory listing (not recursive; subdirectories' docs stay one click away). Render the section only when ≥1 markdown file exists. - Tab switching is client-side state (no route change required, but deep-linkable `#` anchor is a plus if cheap); content rendered through the existing markdown-lite + sanitizer pipeline (same as blob MD preview). - Large files: reuse the blob `too_large` cap behavior (don't render megabytes of markdown). - Filenames with special characters must not break tabs or anchors. ## Acceptance criteria - [ ] README first + alphabetical rest, per-directory; section hidden when no markdown files. - [ ] `node --test` green; browser check (dir with README + several .md, dir with none, case variants) both themes, zero console errors; no new deps.
Author
Owner

Fixed by #171 (#171) — markdown tabs in the Tree view, README-first, client-side tab state, existing markdown-lite + sanitizer pipeline, blob too_large cap reused, special-char-safe anchors/paths. node tests 359/359 green; browser CDP 12/12, zero console errors, dark + light.

Fixed by #171 (https://git.packden.us/crueber/walhub/pulls/171) — markdown tabs in the Tree view, README-first, client-side tab state, existing markdown-lite + sanitizer pipeline, blob too_large cap reused, special-char-safe anchors/paths. node tests 359/359 green; browser CDP 12/12, zero console errors, dark + light.
Author
Owner

Review of PR #171 (fix/issue-170, commit f80d59f + review wording tweak a3bf2c4). Verified in scratch worktree: node suite 359/359 pass (incl. doctabs.test.js 14/14), vite build OK (122 modules) + esbuild SDK bundle OK. No browser drive (node tests + reasoning only, per instructions).

PASS (all checklist items):

  • Ordering (web/src/lib/doctabs.js:24-46): README case-insensitive across both extensions first, rest alphabetical case-insensitive; raw-spelling tie-break is deterministic across locales (no localeCompare ICU variance). Multiple-README edge stable and tested.
  • Non-md fallback (doctabs.js:56-64): probed non-md readme appended trailing, no duplicate when md (includes-check); section hidden when empty. Default-selecting the md head over a trailing non-md probe is a slight change from the old single-readme render but sane and documented.
  • Cache sharing (web/src/pages/Tree.jsx:98-110): key sha:{rev}:blob:{rawPath} matches the blob page sKey format (web/src/lib/data.js:339); pre-fill means zero fetch for the probed readme. Fixed one wording nit directly (a3bf2c4): docs/comment now say 'zero round trips for the pre-filled probed readme, one per newly opened tab' (a non-probed default tab does fetch once on mount).
  • too_large/binary (Tree.jsx:143-152) verbatim matches Blob.jsx:88-95 incl. the 2 MiB cap note. Old single-readme block fully replaced, no dead code or orphan CSS. No new deps (4 files touched, no package manifest changes). Dark+light via shared .pill/.card/.markdown-body incl. dark: selected state.
  • Anchors (doctabs.js:76-108): encodeURIComponent/decode round-trip with malformed-% fallback to default; tested with spaces/quotes/unicode/#. Keyboard: roving tabindex, arrows wrap, Home/End, focus follows via data-index; roles/aria-selected/aria-controls present.
  • Path encoding: docBlobPath per-segment encoding round-trips the backend (internal/server/router.go:187,243-250,334 splits EscapedPath then PathUnescapes per segment, so '/' stays a separator). Confirmed the pre-existing Blob page IS broken the same way for '#'/‘?'/‘%' names (web/sdk/src/repo.js:132-134 interpolates the raw path); leaving that SDK-wide fix out of scope is correct — it needs a backend+SDK contract change, not a Tree.jsx patch.
  • Laws: L1 no new deps, L7 short fetches with loading placeholder (no silent spinner), L8 web-only + doc change (no core-package or seam changes), L12 decision appended in docs/go/12_web_ui.md:490 in the same change.

Small fix pushed to origin/fix/issue-170 (a3bf2c4, comment + doc wording only, suite re-run green). No structural issues. MERGE RECOMMENDATION: ready to merge.

Review of PR #171 (fix/issue-170, commit f80d59f + review wording tweak a3bf2c4). Verified in scratch worktree: node suite 359/359 pass (incl. doctabs.test.js 14/14), vite build OK (122 modules) + esbuild SDK bundle OK. No browser drive (node tests + reasoning only, per instructions). PASS (all checklist items): - Ordering (web/src/lib/doctabs.js:24-46): README case-insensitive across both extensions first, rest alphabetical case-insensitive; raw-spelling tie-break is deterministic across locales (no localeCompare ICU variance). Multiple-README edge stable and tested. - Non-md fallback (doctabs.js:56-64): probed non-md readme appended trailing, no duplicate when md (includes-check); section hidden when empty. Default-selecting the md head over a trailing non-md probe is a slight change from the old single-readme render but sane and documented. - Cache sharing (web/src/pages/Tree.jsx:98-110): key sha:{rev}:blob:{rawPath} matches the blob page sKey format (web/src/lib/data.js:339); pre-fill means zero fetch for the probed readme. Fixed one wording nit directly (a3bf2c4): docs/comment now say 'zero round trips for the pre-filled probed readme, one per newly opened tab' (a non-probed default tab does fetch once on mount). - too_large/binary (Tree.jsx:143-152) verbatim matches Blob.jsx:88-95 incl. the 2 MiB cap note. Old single-readme block fully replaced, no dead code or orphan CSS. No new deps (4 files touched, no package manifest changes). Dark+light via shared .pill/.card/.markdown-body incl. dark: selected state. - Anchors (doctabs.js:76-108): encodeURIComponent/decode round-trip with malformed-% fallback to default; tested with spaces/quotes/unicode/#. Keyboard: roving tabindex, arrows wrap, Home/End, focus follows via data-index; roles/aria-selected/aria-controls present. - Path encoding: docBlobPath per-segment encoding round-trips the backend (internal/server/router.go:187,243-250,334 splits EscapedPath then PathUnescapes per segment, so '/' stays a separator). Confirmed the pre-existing Blob page IS broken the same way for '#'/‘?'/‘%' names (web/sdk/src/repo.js:132-134 interpolates the raw path); leaving that SDK-wide fix out of scope is correct — it needs a backend+SDK contract change, not a Tree.jsx patch. - Laws: L1 no new deps, L7 short fetches with loading placeholder (no silent spinner), L8 web-only + doc change (no core-package or seam changes), L12 decision appended in docs/go/12_web_ui.md:490 in the same change. Small fix pushed to origin/fix/issue-170 (a3bf2c4, comment + doc wording only, suite re-run green). No structural issues. MERGE RECOMMENDATION: ready to merge.
Author
Owner

Fixed by PR #171 incl. review doc fixup (README-first tabs, lazy shared-cache fetch, encoded anchors; 359/359 node tests), merged. Closing.

Fixed by PR #171 incl. review doc fixup (README-first tabs, lazy shared-cache fetch, encoded anchors; 359/359 node tests), merged. Closing.
crueber added this to the v1 milestone 2026-09-10 22:27:16 +00:00
Sign in to join this conversation.
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
crueber/walhub#170
No description provided.