Skip to content

feat(renderer): inline CSV table rendering#1277

Closed
bergeouss wants to merge 5 commits intonesquena:masterfrom
bergeouss:feat/csv-table-rendering
Closed

feat(renderer): inline CSV table rendering#1277
bergeouss wants to merge 5 commits intonesquena:masterfrom
bergeouss:feat/csv-table-rendering

Conversation

@bergeouss
Copy link
Copy Markdown
Contributor

Summary

Closes #485

Extends the inline rendering pipeline to support CSV data — both fenced code blocks and MEDIA: file references render as styled, scrollable HTML tables instead of raw text.

Changes

static/ui.js (+51 lines)

  • Fenced csv blocks: New handler in the fence stash (line ~916) that parses CSV content into <table> HTML with <thead>/<tbody>. Falls back to <pre><code> if fewer than 2 rows.
  • _CSV_EXTS regex: New extension matcher for .csv files
  • MEDIA: CSV files: Lazy-load via loadCsvInline() (same pattern as loadDiffInline()). Fetches via api/media, parses CSV, renders as table.
  • Auto-separator detection: Detects comma, semicolon, or tab as separator based on first line content
  • Quote stripping: Removes surrounding " or ' from CSV fields
  • Line ending normalization: Handles CRLF (\r\n), CR (\r), and LF (\n)
  • Size cap: 256 KB limit with i18n error message for oversized files
  • Error handling: Network errors and empty data display user-friendly messages

static/style.css (+9 lines)

  • .csv-table-wrap — Scrollable container with border and background
  • .csv-table — Full-width table with collapse
  • .csv-table th — Sticky header with hover background
  • .csv-table td — Padded cells with bottom border
  • .csv-table tbody tr:hover — Row hover highlight

static/i18n.js (+28 lines)

  • 4 new keys: csv_loading, csv_too_large, csv_no_data, csv_error
  • Added to all 7 locales

tests/test_csv_table_rendering.py (+139 lines)

  • 15 tests covering: regex, fence handler, table structure, fallback, lazy-load, separator detection, quote stripping, error handling, line endings, i18n, CSS, size cap

Testing

pytest tests/ -v → 57/57 passed
node --check static/ui.js → OK
node --check static/i18n.js → OK

AI Disclosure

Developed with AI assistance (Claude, Hermes Agent).

…esquena#568)

- Add select mode toggle button at bottom of session list
- Render checkboxes per session item when in select mode
- Batch action bar with Archive, Delete, and Move to Project actions
- Select/Deselect all controls in the session select bar
- Escape key exits select mode
- 11 new i18n keys across all 7 locales
- 11 new tests covering state, functions, DOM, CSS, and i18n
- SVG files (local + URL) render as inline <img> with label
- Audio files render as inline <audio> player with controls
- Video files render as inline <video> player with controls
- File attachments in composer also get inline previews
- 3 new i18n keys across all 7 locales
- 14 new tests covering regex, handlers, CSS, i18n, and ordering
- test_renderer_js_behaviour.py: add _SVG_EXTS, _AUDIO_EXTS, _VIDEO_EXTS
  to node driver to prevent ReferenceError when renderMd references them
- test_issue1095_pasted_images.py: widen renderTray window (1200->2500)
  and attachment block window (1200->2000) to account for SVG/audio/video
  handler code inserted before paperclip fallback and blob URL revocation
- test_issue1095_pasted_images.py: use .attach-thumb{ selector (with brace)
  to avoid matching .attach-thumb--svg variant which has no object-fit
…A files (nesquena#485)

- Fenced csv blocks render as styled HTML tables
- MEDIA: CSV files lazy-load and render as tables with auto-separator detection
- Auto-detects comma, semicolon, and tab separators
- Strips surrounding quotes from CSV fields
- Normalizes line endings (CRLF, CR, LF)
- Size cap (256 KB) and error handling with i18n messages
- 4 new i18n keys across all 7 locales
- 15 new tests
@bergeouss bergeouss force-pushed the feat/csv-table-rendering branch from cad2332 to b69ef0b Compare April 29, 2026 22:06
@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Thanks for this PR! Closes #485.

What this does: Extends the inline rendering pipeline to handle CSV data in two ways: fenced ```csv ``` code blocks render as styled HTML tables inline, and MEDIA: references to .csv files lazy-load via api/media and render the same way. Auto-detects comma/semicolon/tab delimiters from the first line, strips surrounding quotes, normalizes line endings.

Scope of changes:

  • static/ui.js — fence handler for CSV blocks, _CSV_EXTS regex, loadCsvInline(), auto-separator detection, quote stripping, 256 KB size cap
  • static/style.css.csv-table-wrap, .csv-table, header/cell/hover styles
  • static/i18n.js — 4 new keys across all 7 locales
  • static/sessions.js — changes included (not described in PR body — see note below)
  • tests/test_csv_table_rendering.py — 15 tests

Things to verify before merge:

  • static/sessions.js is listed in the changed files but not mentioned in the PR description. Worth a quick check that those changes are intentional and scoped to CSV rendering (or split out if unrelated).
  • The auto-separator detection reads the first line — if a CSV has quoted fields containing commas and no non-quoted commas in the header row, it could misdetect the separator. This is an edge case, but worth a comment in the code noting the heuristic.
  • The <thead> uses the first row as headers. For CSV files without a header row, the first data row will be promoted to headers. This is a common convention but worth documenting in the UI (e.g., a small label: "first row treated as header").

Good implementation that follows the established inline render pattern. 15 tests passing.

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

✅ Merged into release branch — included in PR #1285 (v0.50.240). Thanks for the contribution!

- Add code comment documenting auto-separator detection heuristic and
  its quoted-field edge case
- Add 'csv_header_note' i18n key across all 7 locales
- Display 'First row shown as table header' label in CSV table header
- Widen test search window to accommodate added lines
- Addresses review feedback on PR nesquena#1277
@bergeouss
Copy link
Copy Markdown
Contributor Author

Review Feedback Addressed

  • Issue: Reviewer asked for (1) confirmation that sessions.js changes are intentional, (2) a comment about the auto-separator detection edge case, (3) a UI label noting the first row is treated as header
  • Fix:
    • Added code comment documenting the auto-separator detection heuristic and its edge case with quoted fields containing commas
    • Added csv_header_note i18n key across all 7 locales
    • Added a subtle label in the CSV table header: "First row shown as table header"
    • Regarding sessions.js: same as noted on PR feat(renderer): inline Excalidraw diagram embed with SVG renderer #1279 — the batch select mode changes are unrelated to CSV rendering and appear to come from a shared parent branch. The maintainer should decide whether to keep or split them
  • Files: static/ui.js, static/i18n.js, tests/test_csv_table_rendering.py

🤖 AI-assisted via Hermes Agent

nesquena-hermes pushed a commit that referenced this pull request Apr 30, 2026
- Add code comment documenting auto-separator detection heuristic and
  its quoted-field edge case
- Add 'csv_header_note' i18n key across all 7 locales
- Display 'First row shown as table header' label in CSV table header
- Widen test search window to accommodate added lines
- Addresses review feedback on PR #1277
nesquena-hermes added a commit that referenced this pull request Apr 30, 2026
## Release v0.50.240

Batch release of 13 PRs that passed full triage + code review + test suite (3199 tests, 0 failures).

---

### Added

- **Compact tool activity mode** (`simplified_tool_calling`, default on) — groups tool calls and thinking traces into a single collapsed "Activity" disclosure card per assistant turn. Also adds a new **Calm Console** theme with earth/slate palette and serif prose. @Michaelyklam#1282
- **PDF first-page preview** — `MEDIA:` `.pdf` files render a canvas thumbnail via PDF.js CDN (4 MB cap). **HTML sandbox iframe** — `.html`/`.htm` files render inline in a sandboxed `<iframe srcdoc>` (256 KB cap). 10 i18n keys × 7 locales. @bergeouss#1280, closes #480 #482
- **Inline Excalidraw diagram preview** — `.excalidraw` files render as pure SVG (no external deps; rectangles, ellipses, diamonds, text, lines, arrows, freehand; 512 KB cap). @bergeouss#1279, closes #479
- **Inline CSV table rendering** — fenced `csv` blocks and `MEDIA:` CSV files render as scrollable HTML tables with auto-separator detection. @bergeouss#1277, closes #485
- **Inline SVG, audio, and video rendering** — SVG as `<img>`, audio as `<audio controls>`, video as `<video controls>`. @bergeouss#1276, closes #481
- **Batch session select mode** — multi-select sessions for bulk Archive/Delete/Move. 11 i18n keys × 7 locales. @bergeouss#1275, closes #568
- **Collapsible skill category headers** — click to collapse/expand without re-render; state persists across filter cycles. @bergeouss#1281
- **`providers.only_configured` setting** — opt-in flag to restrict the model picker to explicitly configured providers. @KingBoyAndGirl#1268
- **OpenCode Go model catalog** — adds Kimi K2.6, DeepSeek V4 Pro/Flash, MiMo V2.5/Pro, Qwen3.6/3.5 Plus. @nesquena-hermes#1284, closes #1269

### Fixed

- **Profile `TERMINAL_CWD` TypeError** — `_build_agent_thread_env()` helper merges env before `_set_thread_env()` call. @hi-friday#1266
- **Service worker subpath cache bypass** — regex now matches `/api/*` under any mount prefix. @Michaelyklam#1278
- **SSE client disconnect leaks** — `TimeoutError`/`OSError` treated as clean disconnects; server backlog 64, threads daemonized; session list renders before saved-session restore. @KayZz69#1267
- **i18n locale corrections** — Korean MCP strings (23), Chinese MCP strings (23), zh-Hant missing keys (41), de missing keys (229). @bergeouss#1274, closes #1273

---

### Test results

```
3199 passed, 2 skipped, 3 xpassed in 72.79s
```

### PRs on hold (not included)

#1265 (draft), #1271 (superseded by #1266), #1272 (skipped XSS tests), #1232 (partial test run), #1222 (review questions open), #1134 (live-server tests), #1132 (superseded by #1134), #1108 (negative UX review), #1084 (empty description)
@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Shipped in release v0.50.240 (PR #1285). Thanks!

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(renderer): inline CSV table rendering

2 participants