Restore backslash escapes before parsing TeX math content#1580
Merged
Conversation
reformatTextData0 rewrites markdown escapes like \$ into a private sentinel before the text is parsed into cells, then restores them afterward with $mdUnescapeRules, which drops the backslash because in body text it only marks the escape. Math content is handed to makeTeXBoxes as a raw string, so the sentinel reached the TeX parser verbatim: "$$\$123.45 / \$6.78$$" came back as boxes reading \[EntityStart]36\[EntityEnd]123.45, which displays as mojibake once those private use characters are reinterpreted, and the template's "input" was left as "$123.45 / $6.78" with the TeX escape stripped. Unescape math with $texUnescapeRules instead, which keeps the backslash. Inside $$...$$ the escape belongs to TeX rather than markdown, so the backslash has to survive: \$ is how TeX renders a literal dollar sign, and likewise \_ and \#. The remaining escaped characters keep whatever meaning TeX assigns the sequence, which still beats passing the sentinel through. The fix sits on the general mathCell definition only. The digits-only and system-name definitions above it can't hold a sentinel, and the fallback to inlineCodeCell returns strings, which $mdUnescapeRules still catches on the way out. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Covers the escape sentinel that reformatTextData0 substitutes for markdown escapes reaching the TeX parser, which rendered "$$\$123.45 / \$6.78$$" as mojibake rather than $123.45 / $6.78. Both TeX tests were confirmed to fail against the code as it stood before the previous commit. Also pins the neighboring markdown path, where the backslash is dropped rather than kept, since the two unescape rule sets are easy to confuse and a fix on one side could quietly change the other. The file is new -- Formatting.wl had no test coverage. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes TeX math rendering in FormatChatOutput when markdown-escaped characters (notably \$) appear inside $$...$$ blocks, by restoring backslash escapes before passing math content to the TeX parser. This aligns math handling with how markdown escapes are already round-tripped elsewhere in reformatTextData0, while preserving TeX’s need to see escapes like \$, \_, and \# intact.
Changes:
- Add a dedicated
$texUnescapeRulesrule set to restore the escape sentinel back to\-prefixed sequences for TeX parsing. - Apply
$texUnescapeRulestomathCellcontent before callingmakeTeXBoxes. - Add a new
Tests/Formatting.wltfile covering TeX-escaped$,_,#, plus a guard test for markdown-body\$behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
Source/Chatbook/Formatting.wl |
Restores backslash escapes from the markdown sentinel before TeX parsing for mathCell strings. |
Tests/Formatting.wlt |
Adds regression and guard tests validating correct TeX-escape handling vs. markdown-body unescaping. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A markdown-escaped character inside a math block was mangled instead of rendered.
$$\$123.45 / \$6.78$$produced garbage where the dollar signs should be.Before, on
main:After:
Root cause
reformatTextData0rewrites markdown escapes like\$into a private sentinel (esc, a\[EntityStart]…\[EntityEnd]pair) before the text is parsed into cells, then restores them afterward with$mdUnescapeRules. Those rules drop the backslash, which is right for body text — there the backslash only marks the escape, so\$should render as a bare$.Math content never takes that path. It is handed to
makeTeXBoxesas a raw string, so the sentinel reached the TeX parser verbatim and came back as the mojibake above, once those private use characters were reinterpreted.The two halves of the
"before"output fail differently, which is worth noting since only one of them is visible to users:"boxes"was mangled by the TeX parser, and no longer contained a sentinel for anything downstream to recognize."input"still held real sentinels, so the outer unescape sweep inreformatTextData0restored them — to a bare$, silently stripping the TeX escape rather than showing mojibake.Fix
Unescape math with the new
$texUnescapeRules, which restores the sentinel to\<char>and keeps the backslash. Inside$$...$$the escape belongs to TeX rather than markdown, so the backslash has to reach the parser:\$is how TeX renders a literal dollar sign, and likewise\_and\#. The remaining escaped characters (`,*,|) keep whatever meaning TeX assigns the sequence, which still beats passing the sentinel through.The change sits on the general
mathCelldefinition only. The digits-only and system-name definitions above it can't hold a sentinel, and the fallback toinlineCodeCellreturns strings, which$mdUnescapeRulesstill catches on the way out.Test plan
Tests/Formatting.wlt— 5/5 pass.Formatting.wlhad no test coverage before this.TeX-Escaped-Dollarpins the reported case;TeX-Escaped-Underscore-And-Hashcovers\_and\#to show the rule generalizes.Markdown-Escaped-Dollaris a guard, not a regression test: it passes both before and after, and pins the neighboring markdown path (\$→$in body text) that this change could otherwise have quietly broken. The two unescape rule sets are easy to confuse.CodeInspectorclean on both changed files.🤖 Generated with Claude Code