Skip to content

fix(components): render TeX bracket delimiters - #396

Merged
lodystage[bot] merged 3 commits into
mainfrom
fix/streamdown-tex-delimiters
Sep 4, 2026
Merged

fix(components): render TeX bracket delimiters#396
lodystage[bot] merged 3 commits into
mainfrom
fix/streamdown-tex-delimiters

Conversation

@lodystage

@lodystage lodystage Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Problem / pressure

Codex and other agents emit TeX parenthesis and bracket math delimiters, while Streamdown renders dollar-delimited math. Those formulas currently appear as literal text.

Summary

  • Normalize complete TeX parenthesis and bracket math pairs before Streamdown block parsing.
  • Preserve code spans, fenced code, escaped delimiters, incomplete streaming input, and source offsets.
  • Add pure normalization and rendered-output regression coverage.

Before / after

Before After
Parenthesis and bracket math appears literally Complete delimiters render through KaTeX
Delimiters inside code may be misinterpreted by a broad rewrite Code spans and fenced code remain literal

Test plan

  • NODE_ENV=test pnpm exec vitest run tests/markdown-math-delimiters.test.ts tests/markdown-streaming-reparse.test.ts --maxWorkers=2 (38 passed)
  • pnpm --filter @lody/components typecheck
  • pnpm check:quick components passed through lint, i18n, Code Collab, and platform checks; the sandbox-blocked public-boundary step was rerun separately
  • pnpm check:public-boundary
  • Prettier check and changed-file oxlint

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e8b89cc8f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +139 to +143
if (cursor === lineStart) {
const fence = markdownFenceAt(value, lineStart);
if (fence) {
opening = null;
cursor = fencedCodeEnd(value, lineStart, fence);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve delimiters in nested fenced code

Handle fenced blocks inside Markdown containers before rewriting delimiters. For example, in > ```tex\n> \(literal\)\n> ````, each line starts with >, so markdownFenceAtnever recognizes the fence and the code payload is changed to$$literal$$; list-nested fences fail similarly. Because MarkdownRenderer` also renders file previews, task bodies, and skill content, this visibly corrupts displayed and copied code rather than merely changing math rendering.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0bfd558033

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +223 to +227
if (cursor === lineStart) {
const fence = markdownFenceAt(value, lineStart);
if (fence) {
opening = null;
cursor = fencedCodeEnd(value, lineStart, fence);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve delimiters in indented code blocks

When Markdown uses a standard four-space-indented code block, such as \(literal\), markdownFenceAt returns null because there is no fence, and the subsequent scan rewrites the displayed and copied source to $$literal$$. Fresh evidence beyond the earlier nested-fence report is this non-fenced CommonMark code form; the normalizer needs to skip indented code blocks as well as fenced blocks and code spans.

Useful? React with 👍 / 👎.

Comment on lines +279 to +283
if (isOpening) {
opening = { kind, index: delimiterIndex };
} else if (opening?.kind === kind) {
replacements.push(opening.index, delimiterIndex);
opening = null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve escaped parentheses in Markdown destinations

When a link or image destination contains Markdown-escaped balanced parentheses, for example [open](src/report\(final\).md), this scan rewrites the destination to src/report$$final$$.md before Streamdown parses it. The agent-file link remains syntactically file-like, so clicking it passes the altered href to the open-file path and targets a nonexistent filename; exclude Markdown destinations from delimiter normalization.

AGENTS.md reference: packages/components/src/lib/AGENTS.md:L31-L40

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8c1c801487

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}

cursor += 1;
if (column >= 4) return lineEndAfter(value, lineStart);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Normalize math in list continuation paragraphs

When a normal list continuation uses four root-relative spaces, such as - explanation\n \(x\), CommonMark removes the list item's two-space content indent and treats the remainder as paragraph indentation, not an indented code block. This absolute-column check nevertheless skips the entire line, so TeX delimiters in commonly formatted list content remain literal; account for the active container indentation before applying the four-column code rule.

Useful? React with 👍 / 👎.

@lodystage
lodystage Bot merged commit d0e5059 into main Sep 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant