I’m building an AI assistant app and have been struggling to display LaTeX content alongside Markdown-rendered text. Currently, I’m using react-native-markdown-display
for Markdown support and the (deprecated) react-native-math-view
for LaTeX.
One solution I attempted was to parse the content with a regex to split out Markdown vs. LaTeX segments, then conditionally render them using <Markdown />
or <MathView />
. While this works to some extent, it introduces significant alignment and formatting issues.
Below is my current MessageRenderer
component, which implements this approach:
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';
import MathView, {MathText} from 'react-native-math-view';
import {textStyle} from "../styles/common.style";
import Markdown from "react-native-markdown-display";
import {MsgType} from "./class/MessageItem";
const MessageRenderer = ({message, type}) => {
const parts = parseMessage(message);
return (
<View style={styles().main}>
{parts.map((part, index) => {
if (part.type === 'text') {
return (
<Markdown
key={index}
style={{ body: type === MsgType.USER ? styles().normalText : styles().assistantNormalText }}
>
{part.content}
</Markdown>
);
} else if (part.type === 'math') {
return (
<MathView
key={index}
math={part.content}
style={styles().mathText}
/>
);
}
return null;
})}
</View>
);
};
const parseMessage = (message) => {
const regex = /\(([sS]*?)\)|\[([sS]*?)\]/g; // Matches math expressions within (...) or [...]
const parts = [];
let lastIndex = 0;
try {
message.replace(regex, (match, group1, group2, index) => {
// Add text content before the current match
if (lastIndex < index) {
parts.push({ type: 'text', content: message.slice(lastIndex, index) });
}
// Add the matched math content
const formula = group1 || group2;
parts.push({ type: 'math', content: formula });
// Update the lastIndex to the end of the current match
lastIndex = index + match.length;
});
// Add any remaining text after the last match
if (lastIndex < message.length) {
parts.push({ type: 'text', content: message.slice(lastIndex) });
}
} catch (e) {
console.log("error", e);
return parts;
}
return parts;
};
const styles = () => {
return StyleSheet.create({
main: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center'
},
normalText: {
...textStyle.Body_4,
color: 'white'
},
mathText: {
...textStyle.Body_4,
marginHorizontal: 2,
color: 'white'
},
assistantNormalText: {
...textStyle.Body3,
color: 'white'
}
});
};
export default MessageRenderer;
Sample Test Data
const message = `
- This is a paragraph with some inline math: \(E = mc^2\).
- Some text with inline math \(a^2 + b^2 = c^2\)
- And block math
\[
e = sum_(n=0)^oo 1/n!
\]
\[
\int_{a}^{b} x^2 dx
\]
Here is a JavaScript code block:
```javascript
function greet() {
console.log("Hello, world!");
}
```
And some more inline math: \(a^2 + b^2 = c^2\).
`;
Question
Is there a more robust or straightforward method to render both Markdown and LaTeX together in React Native without resorting to manually parsing the content via regex?