Skip to content

fix(markdown): avoid parsing currency as LaTeX - #1997

Merged
Div627 merged 4 commits into
mainfrom
codex/fix-x-markdown-latex-currency
Aug 10, 2026
Merged

fix(markdown): avoid parsing currency as LaTeX#1997
Div627 merged 4 commits into
mainfrom
codex/fix-x-markdown-latex-currency

Conversation

@Div627

@Div627 Div627 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

🤔 This is a ...

  • 🐞 Bug fix
  • ✅ Test Case

🔗 Related Issues

No existing issue or pull request matched this bug.

💡 Background and Solution

The built-in x-markdown LaTeX tokenizer currently treats any text between two $ characters as math. Prose containing multiple currency amounts, such as Downgrade Max ($100) to Pro ($20), is therefore rendered as KaTeX. CJK prose also causes repeated unicodeTextInMathMode warnings because natural-language text is passed into KaTeX math mode.

This change:

  • separates dollar-delimited math from \(...\) and \[...\] parsing;
  • requires matching $/$$ delimiter lengths;
  • applies Pandoc-compatible rules to single-dollar math: no whitespace immediately inside the delimiters, and no digit immediately after the closing $;
  • preserves valid numeric-leading formulas such as $2x + 1$ and all existing double-dollar behavior;
  • adds English, CJK, multiple-price, delimiter-boundary, and warning regression coverage.

Validation:

  • npm exec --workspace packages/x-markdown -- jest --config .jest.js --runInBand --no-cache — 7 suites, 338 tests, 28 snapshots passed.
  • npm run tsc --workspace packages/x-markdown — passed.
  • npm exec --workspace packages/x-markdown -- biome check src/plugins/Latex/index.ts src/plugins/Latex/__tests__/index.test.tsx — passed.
  • Full package biome lint remains blocked by two pre-existing noDangerouslySetInnerHtml errors in benchmark-only MarkdownRenderer.tsx; neither file is touched by this PR.

Reference: Pandoc's tex_math_dollars delimiter rules: https://pandoc.org/demo/example26.html

📝 Change Log

Language Changelog
🇺🇸 English Prevent currency amounts in prose from being interpreted as LaTeX formulas. Single-dollar math now follows Pandoc's delimiter rules, so $ x $ (padded with spaces) and $x$2 no longer render as math; $$...$$ is unaffected.
🇨🇳 Chinese 修复正文中的美元金额被误识别为 LaTeX 公式的问题。行内单美元公式改为遵循 Pandoc 定界符规则,$ x $(首尾带空格)与 $x$2 不再渲染为公式;$$...$$ 不受影响。

Summary by CodeRabbit

  • Bug 修复
    • 优化行内 LaTeX 公式识别,避免将货币金额误渲染为数学公式。
    • 支持公式内部的转义美元符号及以数字开头的公式正常渲染。
    • 按规范过滤空格位置不当或缺少有效边界的单美元分隔符。
    • 保持双美元、括号定界及块级公式的正常解析。

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

LaTeX 插件拆分美元公式与括号定界匹配,并增加单美元定界合法性校验。测试覆盖货币文本、转义美元符号、数字开头公式、空格规则、尾随数字规则及双美元公式。

Changes

LaTeX 解析规则

Layer / File(s) Summary
美元定界匹配与校验
packages/x-markdown/src/plugins/Latex/index.ts
新增独立的美元定界规则和合法性校验。\(...\)\[...\] 继续使用非标准定界规则。
Tokenizer 分支与行为测试
packages/x-markdown/src/plugins/Latex/index.ts, packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx
Tokenizer 分别处理美元和括号匹配结果。测试验证货币文本、转义美元符号、数字开头公式、单美元边界规则、双美元公式及符合 Pandoc 规则的货币文本。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • ant-design/x#1859:同样修改 LaTeX 插件的行内标记解析和渲染测试。

Suggested reviewers: afc163

Poem

兔耳检查美元符,
金额留在原文中。
$2x+1$ 正常发光,
双美元继续成公式,
KaTeX 稳稳渲染中。

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了本次变更的主要目的,即修复 Markdown 中将货币金额误解析为 LaTeX 的问题。
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.
✨ 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 codex/fix-x-markdown-latex-currency

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Bundle Report

Changes will decrease total bundle size by 47 bytes (-0.0%) ⬇️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
antdx-array-push 2.11MB -47 bytes (-0.0%) ⬇️

Affected Assets, Files, and Routes:

view changes for bundle: antdx-array-push

Assets Changed:

Asset Name Size Change Total Size Change (%)
antdx.min.js -47 bytes 2.11MB -0.0%

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Performance benchmark report not found.


This comment is automatically generated by the x-markdown performance CI.

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.07%. Comparing base (b529d8e) to head (7dff501).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1997   +/-   ##
=======================================
  Coverage   97.06%   97.07%           
=======================================
  Files         159      159           
  Lines        5767     5775    +8     
  Branches     1700     1704    +4     
=======================================
+ Hits         5598     5606    +8     
  Misses        167      167           
  Partials        2        2           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 29, 2026

Copy link
Copy Markdown

Deploying ant-design-x with  Cloudflare Pages  Cloudflare Pages

Latest commit: d79a244
Status: ✅  Deploy successful!
Preview URL: https://657bcaeb.ant-design-x.pages.dev
Branch Preview URL: https://codex-fix-x-markdown-latex-c.ant-design-x.pages.dev

View logs

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size
packages/x/dist/antdx.min.js 510.81 KB
packages/x-sdk/dist/x-sdk.min.js 55.71 KB
packages/x-markdown/dist/x-markdown.min.js 34.55 KB
packages/x-markdown/dist/plugins/latex.min.js 61.95 KB (+41 B 🔺)

@Div627
Div627 marked this pull request as ready for review July 29, 2026 08:32
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@dosubot dosubot Bot added bug Something isn't working javascript Pull requests that update Javascript code labels Jul 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@packages/x-markdown/src/plugins/Latex/index.ts`:
- Line 6: Update inlineDollarRule to recognize escaped dollar signs within LaTeX
content, so sequences such as \${} are not treated as closing delimiters;
preserve the existing single- and double-dollar delimiter handling and length
limit, and add a regression test covering $\text{\$100}$.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 06c91106-05ec-4050-af4a-0fc267bfb5b9

📥 Commits

Reviewing files that changed from the base of the PR and between 2c3146a and 46ae60f.

📒 Files selected for processing (2)
  • packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx
  • packages/x-markdown/src/plugins/Latex/index.ts

Comment thread packages/x-markdown/src/plugins/Latex/index.ts Outdated
@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Jul 29, 2026
…imits

Pin down what the Pandoc rules do and do not change:

- `$ x $` (padded on both sides) no longer renders as math — this is the
  behavior change that makes currency detection possible, so assert it
  rather than leaving it implied by `$ x$` / `$x $`.
- `$$ ... $$` is exempt from the spacing rules and still renders padded
  content, so the change is scoped to single-dollar math.
- Currency that happens to satisfy the rules (`价格 $5和$X`) is still parsed
  as math; record it as a known limitation instead of a silent gap.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

⚠️ Performance benchmark report not found.


This comment is automatically generated by the x-markdown performance CI.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx (1)

25-33: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

确保断言失败时也恢复 console.warn

Line 33 的 warnSpy.mockRestore() 位于所有断言之后。如果 render 或任一断言抛出异常,Line 33 不会执行。后续测试可能继续使用被替换的 console.warn,从而隐藏警告并造成测试顺序依赖。请使用 try/finally,或在 afterEach 中统一调用 jest.restoreAllMocks()

建议的局部修复
     const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
-    const { container } = render(
-      <XMarkdown config={{ extensions: latexPlugin() }}>{`**${content}**`}</XMarkdown>,
-    );
-
-    expect(container.querySelector('.katex')).not.toBeInTheDocument();
-    expect(container.querySelector('strong')).toHaveTextContent(content);
-    expect(warnSpy.mock.calls.flat().join(' ')).not.toContain('unicodeTextInMathMode');
-    warnSpy.mockRestore();
+    try {
+      const { container } = render(
+        <XMarkdown config={{ extensions: latexPlugin() }}>{`**${content}**`}</XMarkdown>,
+      );
+
+      expect(container.querySelector('.katex')).not.toBeInTheDocument();
+      expect(container.querySelector('strong')).toHaveTextContent(content);
+      expect(warnSpy.mock.calls.flat().join(' ')).not.toContain('unicodeTextInMathMode');
+    } finally {
+      warnSpy.mockRestore();
+    }
🤖 Prompt for 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.

In `@packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx` around lines
25 - 33, 在 Latex 测试中围绕 console.warn 的 spy 和相关 render/assert 调用加入可靠的清理机制,确保
render 或任一断言失败时仍会执行 warnSpy.mockRestore();可使用 try/finally,或通过 afterEach 统一调用
jest.restoreAllMocks()。
🧹 Nitpick comments (2)
packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx (2)

44-58: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

补充不等长美元分隔符的负向用例。

当前参数表覆盖了空格规则和尾随数字规则,但没有验证 $$x$$x$$ 被拒绝。请加入这两个输入,并继续断言不生成 .katex 且保留原始文本。

建议增加的用例
     '$ x $',
     '$x$2',
+    '$$x$',
+    '$x$$',
🤖 Prompt for 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.

In `@packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx` around lines
44 - 58, 在单美元分隔符参数化测试中补充 `$$x$` 和 `$x$$` 两个输入,继续通过现有断言验证不生成 `.katex` 且保留原始文本。

60-71: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

补充美元与非标准定界符交错的回归用例。

当前用例只覆盖美元语法。请增加 \[a\] and $b$$a$ and \[b\] 等输入,并断言生成两个 .katex 节点且顺序正确。这样可以验证美元匹配分支不会跳过或重排 \(...\)\[...\] 分支。

建议增加的测试
+  it.each([
+    '\\[a\\] and $b$',
+    '$a$ and \\[b\\]',
+  ])('should preserve mixed delimiter order: %s', (content) => {
+    const { container } = render(
+      <XMarkdown config={{ extensions: latexPlugin() }}>{content}</XMarkdown>,
+    );
+
+    expect(container.querySelectorAll('.katex')).toHaveLength(2);
+  });
🤖 Prompt for 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.

In `@packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx` around lines
60 - 71, 在现有 Latex spacing 回归测试中补充美元语法与非标准定界符交错的输入,至少覆盖 `\[a\] and $b$` 与 `$a$
and \[b\]`;对每个输入断言生成两个按源文本顺序排列的 `.katex` 节点,确保美元匹配分支不跳过或重排其他定界符。
🤖 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.

Outside diff comments:
In `@packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx`:
- Around line 25-33: 在 Latex 测试中围绕 console.warn 的 spy 和相关 render/assert
调用加入可靠的清理机制,确保 render 或任一断言失败时仍会执行 warnSpy.mockRestore();可使用 try/finally,或通过
afterEach 统一调用 jest.restoreAllMocks()。

---

Nitpick comments:
In `@packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx`:
- Around line 44-58: 在单美元分隔符参数化测试中补充 `$$x$` 和 `$x$$` 两个输入,继续通过现有断言验证不生成 `.katex`
且保留原始文本。
- Around line 60-71: 在现有 Latex spacing 回归测试中补充美元语法与非标准定界符交错的输入,至少覆盖 `\[a\] and
$b$` 与 `$a$ and \[b\]`;对每个输入断言生成两个按源文本顺序排列的 `.katex` 节点,确保美元匹配分支不跳过或重排其他定界符。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 058fbec4-2553-4135-830a-f83597612c50

📥 Commits

Reviewing files that changed from the base of the PR and between 46ae60f and ed87553.

📒 Files selected for processing (1)
  • packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx

`[^$]` treated the `$` in `\$` as a closing delimiter, truncating
formulas like `$\text{\$100}$`. Allow backslash-escaped characters in
the inline dollar rule so escaped dollars stay inside the formula.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx (1)

25-33: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

请确保断言失败时也恢复 console.warn spy。

如果 Line 26-28 的 render 或 Line 30-32 的任一断言失败,Line 33 不会执行。warnSpy 会继续 mock 后续测试的 console.warn,导致后续 warning 检查失真。请使用 try/finally,或在 afterEach 中统一恢复 mock。

建议修复
 const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
- const { container } = render(
-   <XMarkdown config={{ extensions: latexPlugin() }}>{`**${content}**`}</XMarkdown>,
- );
-
- expect(container.querySelector('.katex')).not.toBeInTheDocument();
- expect(container.querySelector('strong')).toHaveTextContent(content);
- expect(warnSpy.mock.calls.flat().join(' ')).not.toContain('unicodeTextInMathMode');
- warnSpy.mockRestore();
+ try {
+   const { container } = render(
+     <XMarkdown config={{ extensions: latexPlugin() }}>{`**${content}**`}</XMarkdown>,
+   );
+
+   expect(container.querySelector('.katex')).not.toBeInTheDocument();
+   expect(container.querySelector('strong')).toHaveTextContent(content);
+   expect(warnSpy.mock.calls.flat().join(' ')).not.toContain('unicodeTextInMathMode');
+ } finally {
+   warnSpy.mockRestore();
+ }
🤖 Prompt for 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.

In `@packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx` around lines
25 - 33, Ensure the console.warn spy created in the test is restored even when
render or any assertion fails. Update the test setup around warnSpy and the
XMarkdown assertions to use try/finally or an afterEach cleanup, preserving the
existing assertions and preventing the mock from leaking into later tests.
🤖 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.

Outside diff comments:
In `@packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx`:
- Around line 25-33: Ensure the console.warn spy created in the test is restored
even when render or any assertion fails. Update the test setup around warnSpy
and the XMarkdown assertions to use try/finally or an afterEach cleanup,
preserving the existing assertions and preventing the mock from leaking into
later tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3cc2a137-4e83-4c26-9b5e-04801d9cb21b

📥 Commits

Reviewing files that changed from the base of the PR and between ed87553 and d79a244.

📒 Files selected for processing (2)
  • packages/x-markdown/src/plugins/Latex/__tests__/index.test.tsx
  • packages/x-markdown/src/plugins/Latex/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/x-markdown/src/plugins/Latex/index.ts

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Performance benchmark report not found.


This comment is automatically generated by the x-markdown performance CI.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Performance benchmark report not found.


This comment is automatically generated by the x-markdown performance CI.

@Div627
Div627 merged commit 7470e60 into main Aug 10, 2026
17 checks passed
@Div627
Div627 deleted the codex/fix-x-markdown-latex-currency branch August 10, 2026 02:07
cc-hearts added a commit to antdv-next/x that referenced this pull request Aug 19, 2026
Follow Pandoc's single-dollar delimiter rules so amounts like ($100) are
no longer detected as inline math:

- split the single-dollar rule from the \\(...\\) / \\[...\\] rules
- reject dollar math with leading/trailing whitespace or a digit right
  after the closing delimiter (currency detection)
- allow backslash-escaped characters (\\$) inside inline formulas so
  escaped dollars stay in the formula
- keep \$\$...\$\$ exempt from the spacing rules

Sync from ant-design/x#1997 (commit 7470e60).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working javascript Pull requests that update Javascript code lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants