Skip to content

feat(chat): render fenced code blocks in user messages#1335

Closed
bergeouss wants to merge 1 commit intonesquena:masterfrom
bergeouss:feat/1325-user-message-fenced-code
Closed

feat(chat): render fenced code blocks in user messages#1335
bergeouss wants to merge 1 commit intonesquena:masterfrom
bergeouss:feat/1325-user-message-fenced-code

Conversation

@bergeouss
Copy link
Copy Markdown
Contributor

Summary

Fenced code blocks (```...```) in user message bubbles now render with syntax highlighting, language headers, and copy buttons — the same `

` pipeline used by `renderMd()` for assistant messages.

Non-fenced text remains escaped HTML (no bold/italic/link interpretation), matching the maintainer-approved scope of "fenced blocks only".

Changes

  • static/ui.js: Added `_renderUserFencedBlocks(text)` function that:

    1. Extracts fenced code blocks and stashes them as placeholders
    2. Escapes remaining text as plain HTML with `
      ` line breaks
    3. Restashes code blocks as `
      ` HTML (with lang header, diff coloring)
    • User message rendering now calls `_renderUserFencedBlocks(content)` instead of `esc(content).replace(/\n/g, '
      ')`
    • Existing `highlightCode()` and `addCopyButtons()` already work on any `pre > code` in the container, so no changes needed there
  • tests/test_1325_user_fenced_code.py: 12 tests covering:

    • Simple fenced blocks with/without language
    • HTML escaping inside code blocks
    • Markdown NOT interpreted in plain text
    • Diff block coloring
    • Multiple code blocks
    • Special characters (ampersands, angle brackets)
    • URLs not rendered as links
    • Inline backticks left as-is

Closes #1325

🤖 Co-authored-by: Hermes Agent

Fenced code blocks () in user message bubbles now render with
syntax highlighting, copy buttons, and language headers — the same pipeline
used for assistant messages.

Non-fenced text remains escaped HTML (no bold/italic/link interpretation),
matching the maintainer-approved scope of 'fenced blocks only'.

Closes nesquena#1325
@bergeouss
Copy link
Copy Markdown
Contributor Author

The test (3.11) failure is a pre-existing flaky test unrelated to this PR:

tests/test_issue765_streaming_persistence.py::TestPeriodicCheckpoint::test_checkpoint_fires_on_activity_counter_increment

This test uses threading with tight timing (time.sleep(0.15) / time.sleep(0.25)) and expects 2 checkpoint saves but only got 1 — a race condition that happens intermittently on slower CI runners, particularly Python 3.11. The test itself is from issue #765 (streaming persistence) and is not touched by this PR.

All other tests pass (3266 passed, 56 skipped, 3 xpassed). This PR only modifies static/chat.js and tests/test_1325_user_message_code_blocks.py. Happy to re-run if a maintainer triggers it.

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Thanks — confirmed, the flaky test_checkpoint_fires_on_activity_counter_increment failure on 3.11 is unrelated to this PR. It's a known timing-sensitive race in tests/test_issue765_streaming_persistence.py (uses time.sleep(0.15) / time.sleep(0.25) and expects 2 checkpoint saves, sometimes only sees 1 on slower CI runners).

It's stabilized in the release batch (#1343) by replacing the polling sleep windows with threading.Event synchronization. Your PR is included in that batch, so once #1343 lands, this CI flake will be gone for follow-up commits here too.

No re-run needed on this branch — it'll get picked up on merge.

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Shipped in v0.50.246 via batch release PR #1343 (merge commit dec4b486). Thanks @bergeouss! 🙏

Live now at https://github.com/nesquena/hermes-webui/releases/tag/v0.50.246.

Released alongside 4 other contributor fixes — see the v0.50.246 entry in CHANGELOG.md.

pull Bot pushed a commit to JamesWilliam1977/hermes-webui that referenced this pull request Apr 30, 2026
pull Bot pushed a commit to JamesWilliam1977/hermes-webui that referenced this pull request Apr 30, 2026
Combines:
- 4 contributor PRs (nesquena#1335 user fenced code, nesquena#1337 mermaid+cache-bust,
  nesquena#1339 fallback_providers list, nesquena#1341 context_length persistence)
- Self-built nesquena#1338 (cancel data-loss + activity panel) — already
  independently APPROVED by nesquena before absorption
- CONTRIBUTORS.md and markdown refresh from nesquena#1340

See CHANGELOG.md for the full list with author credit.
GeoffBao pushed a commit to GeoffBao/hermes-webui that referenced this pull request May 1, 2026
GeoffBao pushed a commit to GeoffBao/hermes-webui that referenced this pull request May 1, 2026
Combines:
- 4 contributor PRs (nesquena#1335 user fenced code, nesquena#1337 mermaid+cache-bust,
  nesquena#1339 fallback_providers list, nesquena#1341 context_length persistence)
- Self-built nesquena#1338 (cancel data-loss + activity panel) — already
  independently APPROVED by nesquena before absorption
- CONTRIBUTORS.md and markdown refresh from nesquena#1340

See CHANGELOG.md for the full list with author credit.
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.

2 participants