Skip to content

Commit 6e4b554

Browse files
committed
fix: fixed #2419
1 parent f7808c8 commit 6e4b554

2 files changed

Lines changed: 69 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@
9393
proper spacing before the wrapped element, while `1=\textcolor{red}{1}` would.
9494
The commands now create atoms with the correct type (`mord`) and use deferred
9595
argument parsing to ensure proper inter-atom spacing.
96+
- **#2419** Fixed parsing of dollar-delimited math expressions when using
97+
`insert()` in text mode. Previously, when inserting strings like
98+
`"La fonction $f$ est croissante"` into a mathfield with `defaultMode="text"`,
99+
the dollar signs and their content were being escaped, preventing proper
100+
math mode switching. The text mode editor now correctly preserves math
101+
regions delimited by `$...$` or `$$...$$` while only escaping special
102+
characters in text regions, allowing mixed text and inline math expressions
103+
to be inserted correctly.
96104
- **#2444** Font style menu items (roman, italic) are now always visible and
97105
properly toggleable. Previously, these items only appeared when text was
98106
selected, and toggling them when positioned after styled text would not work

src/editor-mathfield/mode-editor-text.ts

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,73 @@ export class TextModeEditor extends ModeEditor {
103103
}
104104

105105
function convertStringToAtoms(s: string, context: ContextInterface): Atom[] {
106+
// If the string contains dollar signs, we need to preserve the math regions
107+
// and only escape special characters in text regions
108+
if (s.includes('$')) {
109+
const segments: string[] = [];
110+
let i = 0;
111+
let inMath = false;
112+
let currentSegment = '';
113+
114+
while (i < s.length) {
115+
if (s[i] === '$') {
116+
// Check for $$
117+
if (i + 1 < s.length && s[i + 1] === '$') {
118+
// Process current text segment before switching modes
119+
if (!inMath && currentSegment) {
120+
segments.push(escapeTextModeCharacters(currentSegment));
121+
currentSegment = '';
122+
} else if (inMath && currentSegment) {
123+
segments.push(currentSegment);
124+
currentSegment = '';
125+
}
126+
segments.push('$$');
127+
inMath = !inMath;
128+
i += 2;
129+
} else {
130+
// Single $
131+
// Process current segment before switching modes
132+
if (!inMath && currentSegment) {
133+
segments.push(escapeTextModeCharacters(currentSegment));
134+
currentSegment = '';
135+
} else if (inMath && currentSegment) {
136+
segments.push(currentSegment);
137+
currentSegment = '';
138+
}
139+
segments.push('$');
140+
inMath = !inMath;
141+
i += 1;
142+
}
143+
} else {
144+
currentSegment += s[i];
145+
i += 1;
146+
}
147+
}
148+
149+
// Process any remaining segment
150+
if (currentSegment) {
151+
if (inMath) {
152+
segments.push(currentSegment);
153+
} else {
154+
segments.push(escapeTextModeCharacters(currentSegment));
155+
}
156+
}
157+
158+
return parseLatex(segments.join(''), { context, parseMode: 'text' });
159+
}
160+
161+
// No dollar signs - escape all special characters as before
162+
return parseLatex(escapeTextModeCharacters(s), { context, parseMode: 'text' });
163+
}
164+
165+
function escapeTextModeCharacters(s: string): string {
106166
// Map special TeX characters to alternatives
107167
// Must do this one first, since other replacements include backslash
108168
s = s.replace(/\\/g, '\\textbackslash ');
109169

110170
s = s.replace(/#/g, '\\#');
111-
s = s.replace(/\$/g, '\\$');
112171
s = s.replace(/%/g, '\\%');
113172
s = s.replace(/&/g, '\\&');
114-
// S = s.replace(/:/g, '\\colon'); // text colon?
115-
// s = s.replace(/\[/g, '\\lbrack');
116-
// s = s.replace(/]/g, '\\rbrack');
117173
s = s.replace(/_/g, '\\_');
118174
s = s.replace(/{/g, '\\textbraceleft ');
119175
s = s.replace(/}/g, '\\textbraceright ');
@@ -123,7 +179,7 @@ function convertStringToAtoms(s: string, context: ContextInterface): Atom[] {
123179
s = s.replace(/~/g, '\\textasciitilde ');
124180
s = s.replace(/£/g, '\\textsterling ');
125181

126-
return parseLatex(s, { context, parseMode: 'text' });
182+
return s;
127183
}
128184

129185
new TextModeEditor();

0 commit comments

Comments
 (0)