Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not working with svelte #104

Closed
4 tasks done
tobiasBora opened this issue Dec 12, 2024 · 7 comments
Closed
4 tasks done

Not working with svelte #104

tobiasBora opened this issue Dec 12, 2024 · 7 comments
Labels
🙋 no/question This does not need any changes 👎 phase/no Post cannot or will not be acted on

Comments

@tobiasBora
Copy link

Initial checklist

Affected package

[email protected]

Steps to reproduce

Rehype-katex does not work with svelte with simple expressions involving \mathbb{N} or \sqrt{x}, apparently due to the fact that svelte interprets {} as a template. Other projects like https://github.com/kwshi/rehype-katex-svelte have been created to solve this issue using instead {@html "..."}, but they seem unmaintained.

To reproduce:

Clone tobiasBora/understand-pid-algo@af0b30e and checkout to the commit af0b30e9ffcfc7b55b19cb5a023b28b3acc20aac, run npm run dev, and visit the home page.

Actual behavior

Observe that you have an error due to the line:

$$x + \frac{1}{\sqrt{2 + \delta}} \in \mathbb{N}$$

the error being on the sqrt:

src/routes/+page.svx:80:15 Expecting Unicode escape sequence \uXXXX
https://svelte.dev/e/js_parse_error

src/routes/+page.svx:80:15

78 |  <p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>+</mo><mfrac><mn>1</mn><msqrt><mrow><mn>2</mn><mo>+</mo><mi>δ</mi></mrow></msqrt></mfrac><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow><annotation
 79 |    encoding="application/x-tex"
 80 |  >x + \frac{1}{\sqrt{2 + \delta}} \in \mathbb{N}</annotation></semantics></math></span><span
                      ^
 81 |    class="katex-html"
 82 |    aria-hidden="true"

Expected behavior

Should work as his expression is valid latex.

Runtime

[email protected]

Package manager

[email protected]

Operating system

NixOs unstable

Build and bundle tools

Vite

@github-actions github-actions bot added 👋 phase/new Post is being triaged automatically 🤞 phase/open Post is being triaged manually and removed 👋 phase/new Post is being triaged automatically labels Dec 12, 2024
@ChristianMurphy
Copy link
Member

ChristianMurphy commented Dec 12, 2024

Welcome @tobiasBora! 👋
That is expected, Rehype handles HTML, Svelte templates are not HTML.
There is no plan or intent to make a svelte mode (or any other non-HTML mode) for the HTML generator in rehype.

That said, there is still a way to handle this.
Instead of trying to treat HTML as Svelte, have rehype render to svelte through its programatic API.
In particular have rehype render JSX constructs (https://github.com/rehypejs/rehype-react) then having Svelte use that programmatic API to safely render to a Svelte component (https://github.com/kenoxa/svelte-jsx).

@ChristianMurphy ChristianMurphy closed this as not planned Won't fix, can't repro, duplicate, stale Dec 12, 2024
@ChristianMurphy ChristianMurphy added the 🙋 no/question This does not need any changes label Dec 12, 2024

This comment has been minimized.

@github-actions github-actions bot added 👎 phase/no Post cannot or will not be acted on and removed 🤞 phase/open Post is being triaged manually labels Dec 12, 2024
@tobiasBora
Copy link
Author

tobiasBora commented Dec 13, 2024

@ChristianMurphy Thanks, even if I'm a bit sad to see that there is no plan to solve this. But I'm curious, would it make sense to allow the user to define a custom wrapper code around the html produced by remark-math? This may be a wrapper like <div class="remark-math">…</div> or, for svelte, {@html "..."}… As such, I guess this is still valid HTML (if you interpret this as a single of tokens I don't see why this would be invalid html), and this would certainly be really easy to implement.

Svelte templates are not HTML.

Out of curiosity, aren't they valid HTML syntaxically? Like in HTML, nothing prevents me from writing Foo {x+1} bar, irrespective of the semantic given by svelte to {x+1}.

That said, there is still a way to handle this. Instead of trying to treat HTML as Svelte, have rehype render to svelte through its programatic API.

Hum interesting, I need to check how far I can go with this. But I guess I will not be able anymore to use svelte-syntax in the html like:

---
title: my title
---
<script>
let x = 1;
</script>

## Introduction

Hey {x + 2}.

EDIT
The approach I mention seems to be the one followed by rehype-katex-svelte here https://github.com/kwshi/rehype-katex-svelte/blob/9144b02ca0bd8a46c08742bcf2f9df77590f70aa/src/index.ts#L30 as they do:

      hastFromString(node, `{@html ${JSON.stringify(rendered)}}`);

(there might be a more efficient way than stringify + parse again… but at least it seems to be parsed correctly by hast as valid HTML)

@wooorm
Copy link
Member

wooorm commented Dec 13, 2024

It would make a lot of sense yes to wrap things. It already exists: that wrapper is mdsvex. That is where Svelte comes in. It turns AST nodes into a string for Svelte to consume.

Note: mdsvex is different from MDX.

MDX itself also supports Svelte, somewhat. It should not have these problems: https://mdxjs.com/docs/getting-started/#jsx.

That being said, Svelte does not itself implement a JSX runtime, which is why svelte-jsx exists. And it might not be perfect yet. You can either improve it, or ask Rich to implement the JSX automatic runtime: sveltejs/svelte#8256 (comment).

@tobiasBora
Copy link
Author

It would make a lot of sense yes to wrap things. It already exists: that wrapper is mdsvex. That is where Svelte comes in. It turns AST nodes into a string for Svelte to consume.

So if my understanding is correct, for now stuff goes like markdown file > rehype-katex > mdsvex > svelte, so when mdsvex sees the AST, it already lost the information that some parts should not be parsed by svelte (unless they look for hardcoded class and exclude some classes from being parsed by svelte if this makes sense?). So it means that this should rather be done by rehype-katex running something like what is done by rehybe-katex-svelte:

      hastFromString(node, `{@html ${JSON.stringify(rendered)}}`);

Regarding MDX it is another option to try if you say it should work, but I guess I lose some of the nice integration between mdsvex and svelte (like I can call a svelte component from the markdown)… And also svelte-jsx seems unmaintained and sveltejs/svelte#8256 mentions it is also buggy, so this seems overkill compared to a ~ one-line addition to rehype-katex…

In the worst case, if neither you nor mdsvex want to implement a solution, would it make sense to create a rehype plugin running right after rehype-katex that picks all div with class like math, math-inline or math-display and surround them with a {@html "…"} code?

@wooorm
Copy link
Member

wooorm commented Dec 13, 2024

I do not know exactly how mdsvex works so I cannot comment exactly on its pipeline.
But it could differentiate between how a human writes in their markdown-like format, and how someone would write HTML in HTML, or how a plugin injects things.
Similarly, In JavaScript, it is known when a human writes a " to start a string. Whereas an escaped " could exist in a string.
MDX also knows when a human writes a < or when a < exists in a string. Or a {.

I am not interested in adding some workaround for you. The proper solution is to either maintain some version of svelte-jsx, there, or in svelte (which makes sense to me because every other framework does that, vue solid preact whatever). Or for mdsvex to know whether a human wrote something or something exists in a string

Indeed, you can also do workarounds with plugins yourself

@tobiasBora
Copy link
Author

Ok, too bad, that's life. Will use rehype-katex-svelte then until a cleaner solution is found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🙋 no/question This does not need any changes 👎 phase/no Post cannot or will not be acted on
Development

No branches or pull requests

3 participants