react-native-marked icon indicating copy to clipboard operation
react-native-marked copied to clipboard

Support Latex?

Open jaswinprakash opened this issue 9 months ago • 4 comments

i have tried the latex example in my app, but the output seems only renders markdown correctly but the latex equation showing as plain text , is this latex feature support in this module? or am i doing anything wrong?

below is my code example

import React from "react";
import Markdown, { Renderer, MarkedTokenizer, MarkedLexer } from "react-native-marked";

class CustomTokenizer extends MarkedTokenizer {
  // Override
  codespan(src) {
    const match = src.match(/^\$+([^\$\n]+?)\$+/);
    if (match?.[1]) {
      const text = match[1].trim();
      const token = {
        type: 'custom',
        raw: match[0], // should be the exact regex pattern match
        identifier: "latex", // Unique identifier for the token
        tokens: MarkedLexer(text), // optional, can be used if the markdown contains children
        args: { // optional, can be used to send more information to the renderer
          text: text,
        }
      };
      return token;
    }

    return super.codespan(src);
  }
}

class CustomRenderer extends Renderer {
  // Custom Token implementation
  custom(identifier, _raw, _children, args) {
    const text = args?.text;
    if (identifier === "latex") {
      const styles = {
        padding: 16,
        minWidth: "100%",
        backgroundColor: "#f6f8fa"
      };
      return this.code(text.trim(), "latex", styles);
    }
    return null;
  }
}

const renderer = new CustomRenderer();
const tokenizer = new CustomTokenizer();

const markdown = `
# 🧠 Markdown with LaTeX

This example showcases **Markdown** combined with _LaTeX_ rendering.

## 📌 Features

- Headings (like this one)
- **Bold**, *Italic*, ~~Strikethrough~~
- [Link](https://reactnative.dev)
- Images: ![React Native](https://reactnative.dev/img/header_logo.svg)
- Blockquotes:
  > Markdown is awesome!
- Lists:
  - Inline math: $a^2 + b^2 = c^2$
  - Block math:
    $$
    \\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}
    $$
- Code:
  \`\`\`js
  const greet = () => console.log("Hello");
  \`\`\`

## 🎯 Inline & Block Math

Text before inline: $E = mc^2$ and after.

And now a block:

$$
\\nabla \\cdot \\vec{E} = \\frac{\\rho}{\\varepsilon_0}
$$

---

> Math + Markdown = ❤️

`;

const ExampleComponent = () => {
  return (
    <Markdown
      value={markdown}
      flatListProps={{
        initialNumToRender: 8,
      }}
      renderer={renderer}
      tokenizer={tokenizer}
    />
  );
};

export default ExampleComponent;

emulator output is shown below,

Image

project details,

"react-native": "0.76.5",
"react": "18.3.1",
"expo": "~52.0.18",
"react-native-marked": "^6.0.7",
"react-native-svg": "^15.10.1",

jaswinprakash avatar Apr 04 '25 11:04 jaswinprakash

Upstream issue https://github.com/markedjs/marked/issues/1948

gmsgowtham avatar Apr 04 '25 16:04 gmsgowtham

As per the regex the output text seems correct.

gmsgowtham avatar Apr 04 '25 16:04 gmsgowtham

As per the regex the output text seems correct.

I don't understand , can you explain more clearly?

jaswinprakash avatar Apr 04 '25 19:04 jaswinprakash

@jaswinprakash There are a couple of things you'll need to consider for implementing this:

  • It won't render anything useful if you don't implement an actual renderer function for that. In your snippet you are simply rendering code, there's nothing to do with latex besides the basic detection.
  • The example regex for detecting is too basic, it won't consider blocks x inline differences, and more.

I recently implemented it using a webview and KaTeX. Keep in mind that KaTeX renders math only while LaTeX is much more, as it can describe full documents. By the examples you showed I think what you'd be looking for is KaTeX as well.

I will leave the rest for you to figure out, since my implementation is done with a DOM component (Expo 52+ only) rather than a plain webview, if I share it as is it would need a lot of extra steps and explanations.

Some tips if you plan to get the webview one going, you'll have to:

  • Calculate the HTML content dimensions in order to auto-size the webview
  • Make sure it scrolls horizontally (in my case I wrapped the webview with a horizontal scrollview)
  • For blocks, make sure it's rendered as a block, otherwise it won't scroll, because inline elements are rendered within Text

winterdouglas avatar Jun 14 '25 14:06 winterdouglas