# Markdown and Latex syntax highlighting

**URL:** https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382
**Category:** Uncategorized
**Created:** [May 14, 2022, 9:35pm UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382 "2022-05-14T21:35:12Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![bzrr](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/bzrr/32/2067_2.png) [@bzrr](https://discuss.codemirror.net/u/bzrr)
#### Post date: [May 14, 2022, 9:35pm UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/1 "2022-05-14T21:35:13Z")

</div>

Hi,

I’m wondering what would be the recommended way to get both Markdown and Latex syntax highlighting working simultaneously, and I noticed there’s a function called `parseMixed` in the `@lezer/common` package to select a different parser for particular nodes. I would want for text surrounded by single (inline math mode) or double (display math mode) dollar-signs to be highlighted as Latex and everything outside as Markdown. Should I read the ranges from each node given by `parseMixed` and find matches with regex or should I extend the `@lezer/markdown` to add new node types for these sections? Also, would I have to modify the markdown table extension to allow for latex within tables?

---

<div class="post-metadata">

### Author: ![marijn](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/marijn/32/136_2.png) [@marijn](https://discuss.codemirror.net/u/marijn)
#### Post date: [May 14, 2022, 9:52pm UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/2 "2022-05-14T21:52:26Z")

</div>

Yes, write an extension for the markdown parser that recognizes dollar sign markup, and either directly integrate the math parsing in there, or use `parseMixed` to enable some kind of LaTeX parsing inside those nodes.

---

<div class="post-metadata">

### Author: ![bzrr](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/bzrr/32/2067_2.png) [@bzrr](https://discuss.codemirror.net/u/bzrr)
#### Post date: [May 15, 2022, 2:23am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/3 "2022-05-15T02:23:10Z")

</div>

I copied the code for the Strikethough extension and made it work with dollar signs. Don’t know if I’m doing this correctly, but the mixed parsing wrapper became simply this:

```
const latexWrapper = parseMixed((node, input) => {
    if (node.type.name === "InlineMath") {
        return { parser };
    }
    return null;
});

```

Problem I’m running into now is that I would like to have a `<div class="cm-math">` wrap the latex elements but I guess the parser replaces the “InlineMath” node with its own nodes. What’s the correct way of doing this?

---

<div class="post-metadata">

### Author: ![bzrr](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/bzrr/32/2067_2.png) [@bzrr](https://discuss.codemirror.net/u/bzrr)
#### Post date: [May 15, 2022, 3:34am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/4 "2022-05-15T03:34:15Z")

</div>

Nevermind. Just had to do:

```
const latexWrapper = parseMixed((node, input) => {
    if (node.type.name === "InlineMath") {
        return { parser, overlay: [{ from: node.from, to: node.to }] };
    }

    return null;
});
```

---

<div class="post-metadata">

### Author: ![bzrr](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/bzrr/32/2067_2.png) [@bzrr](https://discuss.codemirror.net/u/bzrr)
#### Post date: [May 15, 2022, 8:25am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/5 "2022-05-15T08:25:52Z")

</div>

@marijn I was able to do the inline parser, but I’m having trouble parsing the latex blocks. This is what I got:

```
parse: (cx: BlockContext, line: Line) => {
    if (!line.text.startsWith("$$")) {
        return false;
    }

    const startFrom = line.pos;
    const startTo = line.pos + 2;

    while (cx.nextLine()) {
        if (line.text.startsWith("$$")) {
            const mark = cx.elt(mathBlockMark, cx.lineStart, cx.lineStart + 2);
            const elt = cx.elt(mathBlockNode, startFrom, startTo, [mark]);
            cx.addElement(elt);
            return true;
        }
    }

    return false;
}

```

Am I doing this correctly?

---

<div class="post-metadata">

### Author: ![marijn](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/marijn/32/136_2.png) [@marijn](https://discuss.codemirror.net/u/marijn)
#### Post date: [May 16, 2022, 7:20am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/6 "2022-05-16T07:20:05Z")

</div>

I’m not sure how this block math markup works, but that code looks a bit dubious — you’re returning false when there’s only a single line prefixed with `$$`, and creating separate mabhBlockNode elements for every prefixed line beyond the first (but not for the first).

---

<div class="post-metadata">

### Author: ![bzrr](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/bzrr/32/2067_2.png) [@bzrr](https://discuss.codemirror.net/u/bzrr)
#### Post date: [May 16, 2022, 8:58am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/7 "2022-05-16T08:58:09Z")

</div>

Yeah, that was a bit off, but I think I figured out how to do it.

```
  parse: (cx: BlockContext, line: Line) => {
      if (!line.text.startsWith("$$")) {
          return false;
      }

      const start = cx.lineStart;
      while (cx.nextLine()) {
          if (line.text.startsWith("$$")) {
              cx.addElement(cx.elt(mathBlockNode, start, cx.lineStart + 2));
              cx.nextLine();
              return true;
          }
      }
      return false;
  }
```

---

<div class="post-metadata">

### Author: ![bzrr](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/bzrr/32/2067_2.png) [@bzrr](https://discuss.codemirror.net/u/bzrr)
#### Post date: [May 21, 2022, 8:03am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/8 "2022-05-21T08:03:22Z")

</div>

So, that ended up not working lol. What I wanna do is parse everything between the dollar signs (including the dollar signs themselves) as a MathBlock, regardless of where they are (I think this is how FencedCode is parsed). I guess doing this with `parseBlock.parse` won’t work since the start of a block doesn’t have to be at the beginning of a line. Anyway, the following examples should all be valid:

Example 1

```auto
$$2x+1$$

```

Example2

```auto
$$
2x+1$$

```

Example 3

```auto
test $$
2x+1
$$

```

Example 4

```auto
test $$
2x+1
$$

```

@marijn How do I go about doing this?

---

<div class="post-metadata">

### Author: ![marijn](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/marijn/32/136_2.png) [@marijn](https://discuss.codemirror.net/u/marijn)
#### Post date: [May 24, 2022, 11:29am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/9 "2022-05-24T11:29:26Z")

</div>

If these can occur in inline text then it looks like you’ll have to define an inline parser for them.

---

<div class="post-metadata">

### Author: ![bxff](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/bxff/32/1915_2.png) [@bxff](https://discuss.codemirror.net/u/bxff)
#### Post date: [May 24, 2022, 12:11pm UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/10 "2022-05-24T12:11:41Z")

</div>

> [@bzrr](#):
>
> `return { parser, overlay: [{ from: node.from, to: node.to }] };`

Hello there, I am also trying to do the same thing, I was wondering what parser are you using, are you using `sTeX` from the legacy parser?

I also managed to create a simple inline parser based off Strikethough extension, and I haven’t used the block parser so I may not be able help you unfortunately ☹.

---

<div class="post-metadata">

### Author: ![personalizedrefriger](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/personalizedrefriger/32/2193_2.png) [@personalizedrefriger](https://discuss.codemirror.net/u/personalizedrefriger)
#### Post date: [June 20, 2022, 2:59am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/11 "2022-06-20T02:59:44Z")

</div>

This is similar to what was included above, but [this is the parser I’m currently using](https://github.com/personalizedrefrigerator/joplin/blob/pr/markdownToolbar/packages/app-mobile/components/NoteEditor/MarkdownTeXParser.ts) to mark regions as `InlineMath` or `BlockMath`.

The variant of markdown the parser is for, however, only supports `$$` at the beginning of a line and uses `$` for inline math.

> [@bxff](#):
>
> I also managed to create a simple inline parser based off Strikethough extension, and I haven’t used the block parser so I may not be able help you unfortunately ☹.

I haven’t tried using it yet, but it looks like [a 3rd-party lezer parser for TeX](https://github.com/mathematic-inc/codemirror-tex/tree/main/packages) exists (`lezer-tex` on `npm`).

---

<div class="post-metadata">

### Author: ![personalizedrefriger](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/personalizedrefriger/32/2193_2.png) [@personalizedrefriger](https://discuss.codemirror.net/u/personalizedrefriger)
#### Post date: [June 24, 2022, 7:35am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/12 "2022-06-24T07:35:55Z")

</div>

A version that uses the `sTeX` parser [can be found here](https://github.com/laurent22/joplin/blob/689931605722ca6d57cafe06b15089613e641b8b/packages/app-mobile/components/NoteEditor/MarkdownTeXParser.ts).

* * *

**Edit** : This post originally contained question about the usage of what I thought was an `@internal` constructor. I was was confused. The original question is below:

> **Details**
>
> This version of the parser does, however, use an `@internal` version of `cx.elt(...)`:
> 
> > <https://github.com/lezer-parser/markdown/blob/main/src/markdown.ts#L901>
> 
> > <https://github.com/laurent22/joplin/blob/689931605722ca6d57cafe06b15089613e641b8b/packages/app-mobile/components/NoteEditor/MarkdownTeXParser.ts#L147>
> 
> I’m using this constructor to nest elements. Is there some other way I should be doing this?

---

<div class="post-metadata">

### Author: ![marijn](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/marijn/32/136_2.png) [@marijn](https://discuss.codemirror.net/u/marijn)
#### Post date: [June 24, 2022, 11:15am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/13 "2022-06-24T11:15:28Z")

</div>

> [@personalizedrefriger](#):
>
> This version of the parser does, however, use an `@internal` version of `cx.elt(...)`:

`BlockContext.elt` is public. Could you elaborate on what is internal about this use?

---

<div class="post-metadata">

### Author: ![personalizedrefriger](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/personalizedrefriger/32/2193_2.png) [@personalizedrefriger](https://discuss.codemirror.net/u/personalizedrefriger)
#### Post date: [June 24, 2022, 11:31am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/14 "2022-06-24T11:31:19Z")

</div>

Sorry! I was confused!

I was looking at the `Element` constructor:

> <https://github.com/lezer-parser/markdown/blob/f94089de559314239630f3b7bd53af4e76f3786a/src/markdown.ts#L1315>

( **which I am not using** ).

---

<div class="post-metadata">

### Author: ![fcollonval](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/fcollonval/32/2575_2.png) [@fcollonval](https://discuss.codemirror.net/u/fcollonval)
#### Post date: [May 9, 2023, 8:43am UTC](https://discuss.codemirror.net/t/markdown-and-latex-syntax-highlighting/4382/15 "2023-05-09T08:43:40Z")

</div>

Thanks a lot for sharing all those information. This allows us to activate mathematical expression highlighting in JupyterLab 4 (that switches to CodeMirror 6). For interested dev, you can have a look at:

> <https://github.com/jupyterlab/jupyterlab/pull/14509/files#diff-426d6528daf62a0a8f0c5fa3457d06bd87d3af477a01913b09c51f449ecf6f98>
>
> \<!--
> Thanks for contributing to JupyterLab!
> Please fill out the following item…s to submit a pull request.
> See the contributing guidelines for more information:
> https://github.com/jupyterlab/jupyterlab/blob/master/CONTRIBUTING.md
> \--\>
> 
> \## References
> 
> 
> Fixes #14155
> 
> 
> \## Code changes
> 
> 
> Add custom Markdown extension to parse LaTeX mathematical expressions.
> 
> \## User-facing changes
> 
> 
> Mathematical expression are highlighted in CodeMirror Markdown editors.
> 
> 
> Before
> !\[image\](https://user-images.githubusercontent.com/8435071/237041897-d44a1912-698d-4bbf-a0d9-b31ff85fa913.png)
> 
> After
> !\[image\](https://user-images.githubusercontent.com/8435071/236884408-61e014a1-2d19-4013-b9d1-9e845c8c1a11.png)
> 
> 
> 
> \## Backwards-incompatible changes
> 
> 
> None
