Skip to content

fix(desktop): prevent shell vars from rendering as math#419

Merged
hiqiancheng merged 2 commits into
mainfrom
fix/markdown-shell-var-katex
Jun 7, 2026
Merged

fix(desktop): prevent shell vars from rendering as math#419
hiqiancheng merged 2 commits into
mainfrom
fix/markdown-shell-var-katex

Conversation

@hiqiancheng

Copy link
Copy Markdown
Collaborator

Summary

Prevents shell-style variables in assistant markdown text from being parsed as KaTeX inline math. This keeps paths and commands such as $env:USERPROFILE\Desktop, $HOME/project, and ${USERPROFILE}\Desktop rendering as normal text while leaving inline code, fenced code, and closed math like $x$ unchanged.

Related issue or RFC

Link the issue or RFC:

For code changes, link the tracking issue. Only documentation wording, link fixes, or comment-only cleanups may skip the issue-first flow.

AI assistance disclosure

If AI tools materially assisted this contribution, disclose that here or point to the relevant commit trailer.

  • Tool(s) used: Codex
  • Scope of assistance: Debugged the markdown/KaTeX rendering issue, implemented the focused parser input guard, and added regression test coverage.
  • Human review or rewrite performed: Author reviewed the final diff before opening the PR.
  • Architecture or boundary impact: No architecture or cross-boundary changes; scoped to MarkdownContent input normalization.

Testing evidence

List the commands you ran and the results you observed.

  • pnpm.cmd --filter @touchai/desktop test:unit --run tests/components/MarkdownContent-i18n.test.ts - passed, 8 tests, in the original workspace with dependencies installed.
  • pnpm.cmd --filter @touchai/desktop test:unit --run tests/views/SearchView/components/ConversationPanel/AssistantMessage.test.ts - passed, 8 tests, in the original workspace with dependencies installed.
  • git diff --check - passed in the clean PR worktree.
  • pnpm.cmd --filter @touchai/desktop test:unit --run tests/components/MarkdownContent-i18n.test.ts in the clean PR worktree could not run because that worktree does not have node_modules installed (vitest was not recognized).
  • pnpm test:pr was not run locally; relying on CI for full-suite evidence.

Did you follow TDD (test-first) for feature and fix work? Strongly recommended. See docs/testing/testing.md.

pnpm test:pr
pnpm test:coverage:rust
pnpm test:e2e

Risk notes

  • AgentService, runtime, MCP, or schema impact: None.
  • database baseline or migration impact: None.
  • release or packaging impact: None.

Screenshots or recordings

N/A. The regression is covered by parser input tests.

Checklist

  • The PR title follows Conventional Commits and is valid for squash merge.
  • This PR is either ready for review or explicitly marked as a Draft PR.
  • I did not use [WIP] or similar title prefixes.
  • If AI materially assisted this PR, I disclosed the tools and scope and I personally reviewed every affected change.
  • I can explain the why, what, and how of this change without relying on an AI tool.
  • If this touches AgentService, runtime, MCP, or schema boundaries, there is an accepted RFC.
  • If this changes architecture or adds a new cross-boundary abstraction, there is an accepted RFC.
  • I ran pnpm test:pr for this code PR, or this is a docs-only change.
  • If I changed Rust behavior or tests, I reviewed pnpm test:coverage:rust or relied on CI coverage evidence.
  • If I changed desktop startup/window/search/popup/settings/E2E paths, I ran pnpm test:e2e locally or documented why CI is the first valid proof.
  • I added tests or explained why tests are not appropriate.
  • I updated docs when behavior changed.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f29b5860-a2a8-4490-89fa-c0c6bfec9f1d

📥 Commits

Reviewing files that changed from the base of the PR and between 4a953d1 and f2ab1a1.

📒 Files selected for processing (2)
  • apps/desktop/src/components/MarkdownContent.vue
  • apps/desktop/tests/components/MarkdownContent-i18n.test.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Rust Checks
  • GitHub Check: Frontend Quality
  • GitHub Check: Frontend Tests
  • GitHub Check: CodeQL (rust)
  • GitHub Check: CodeQL (javascript-typescript)
  • GitHub Check: Desktop E2E Smoke (Windows)
🔇 Additional comments (4)
apps/desktop/src/components/MarkdownContent.vue (3)

157-181: LGTM!


183-190: LGTM!


232-236: LGTM!

apps/desktop/tests/components/MarkdownContent-i18n.test.ts (1)

85-100: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Shell-variable-like sequences in markdown are now escaped when outside code or math spans, preventing unintended rendering or formatting.
  • Tests
    • Added coverage to verify markdown handling preserves code and math spans while escaping shell-variable patterns.

Walkthrough

MarkdownContent.vue now preprocesses markdown content to escape shell-variable patterns ($HOME, ${env:VAR}) before parsing, preventing KaTeX from misinterpreting them as inline math. The escaping respects code block and backtick boundaries. A test validates the escaping behavior.

Changes

Shell Variable Escaping for Markdown

Layer / File(s) Summary
Shell variable escaping utility
apps/desktop/src/components/MarkdownContent.vue
Added escapeShellVariablesOutsideCode() helper that detects shell-variable patterns beginning with $ and escapes them with backslashes while tracking state to skip content inside fenced code blocks and backtick-quoted code.
Markdown parser integration
apps/desktop/src/components/MarkdownContent.vue
Updated markdownParseInput computed property to preprocess props.content through the escaping utility before passing to the markdown parsing pipeline.
Test verification
apps/desktop/tests/components/MarkdownContent-i18n.test.ts
Added test case that mounts MarkdownContent with mixed shell variables, math expressions, and backtick code, asserting that the parser receives escaped shell-variable patterns while preserving other content.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit hops through dollars and braces,
Escaping the $ in all the right places,
Outside of the code fences, safe from the sight,
Where KaTeX was dancing with $...$ tonight.
Now markdown flows pure, with variables in chains! 🐰💫

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(desktop): prevent shell vars from rendering as math' follows Conventional Commits format with proper scope and clearly describes the main change.
Description check ✅ Passed The PR description is comprehensive with all major sections completed: summary, related issue, AI assistance disclosure, testing evidence, risk notes, and checklist items marked.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/markdown-shell-var-katex

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

@github-actions github-actions Bot added the area:frontend Frontend UI or view-layer changes label Jun 4, 2026
@hiqiancheng hiqiancheng force-pushed the fix/markdown-shell-var-katex branch from bc0ee04 to 4a953d1 Compare June 4, 2026 19:26
@hiqiancheng hiqiancheng marked this pull request as ready for review June 7, 2026 14:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/components/MarkdownContent.vue`:
- Around line 157-165: shouldEscapeShellVariable currently escapes when the
character after the regex match isn't '$', which misclassifies inline math like
`$x+y$` because the regex matches only `$x` and the following '+' triggers an
escape; update shouldEscapeShellVariable to inspect the character immediately
after the matched token (const end = index + match[0].length) and return true
only if that nextChar is '$' or a character that legally continues a shell
variable (e.g., alphanumeric or '_') — treat operator characters used in math
(like + - * / ^ = and whitespace) as non-shell continuations so the function
returns false for math expressions; apply the same fix to the analogous logic
around the other occurrence referenced (the block mirrored at the second
location).

In `@apps/desktop/tests/components/MarkdownContent-i18n.test.ts`:
- Around line 85-100: Update the test in MarkdownContent-i18n.test.ts so it also
asserts a non-trivial inline math expression is preserved (not escaped) by
adding an example like $x+y$ (or $x_i$) to the props.content string passed to
mount(MarkdownContent) and to the expected string passed to
parseMarkdownToStructureMock; keep shell-variable occurrences escaped (e.g.
\\$HOME, \\${USERPROFILE}) but ensure the math substring remains unescaped (e.g.
... math: $x+y$; ...) so parseMarkdownToStructureMock is expected to receive the
preserved inline math while still escaping shell variables.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 23830e6f-a89a-4fc9-96f9-45b9aa6da2e1

📥 Commits

Reviewing files that changed from the base of the PR and between 36044b6 and 4a953d1.

📒 Files selected for processing (2)
  • apps/desktop/src/components/MarkdownContent.vue
  • apps/desktop/tests/components/MarkdownContent-i18n.test.ts

Comment thread apps/desktop/src/components/MarkdownContent.vue
Comment thread apps/desktop/tests/components/MarkdownContent-i18n.test.ts
@hiqiancheng hiqiancheng added this pull request to the merge queue Jun 7, 2026
Merged via the queue into main with commit bd98f76 Jun 7, 2026
27 checks passed
@hiqiancheng hiqiancheng deleted the fix/markdown-shell-var-katex branch June 7, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:frontend Frontend UI or view-layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant