Closed fhg-isi closed 8 months ago
Thanks for opening your first issue here! Engagement like this is essential for open source projects! :hugs:
If you haven't done so already, check out EBP's Code of Conduct. Also, please try to follow the issue template as it helps other community members to contribute more effectively.
If your issue is a feature request, others may react to it, to raise its prominence (see Feature Voting).
Welcome to the EBP community! :tada:
Hi @fhg-isi, thanks for opening this issue! It looks like our documentation is slightly out of date.
I'm new to the nitty-gritty of getting this up and running, but did some digging around. I can provide a solution, but do keep an eye on this thread in case one of the team provides a superior alternative.
The error that you're seeing is caused by missing JS dependencies. You need to ensure that your script is being executed in a context where those modules have been loaded. The easiest solution in most modern browsers is to use a <script type="module">
tag to make use of the import
statement:
<html>
<head>
<link rel="stylesheet" type="text/css" href="myst.css">
</head>
<div id="output"></div>
<script type="module">
import { unified } from 'https://esm.sh/unified@10.1.2?bundle'
import { mystParser } from 'https://esm.sh/myst-parser@1.0.21?bundle'
import { State, transform, mystToHast, formatHtml } from 'https://esm.sh/myst-to-html@1.0.21?bundle'
import rehypeStringify from 'https://esm.sh/rehype-stringify@9.0.3?bundle'
const pipe = unified()
.use(mystParser)
.use(transform, new State())
.use(mystToHast)
.use(formatHtml)
.use(rehypeStringify);
const result = pipe.processSync(':::{important}\nHello to the world!\n:::');
document.getElementById('output').innerHTML = result.value;
</script>
</body>
</html>
You can see that this is very close to what the documentation already suggests, but it's a mix of the Node and browser examples. You'll also need a stylesheet, (here, myst.css
) of which an example is given in https://github.com/executablebooks/mystmd/blob/690f4695bb172d5a0aa05c0f4600064540528029/packages/myst-parser/myst.css. Note that this is not a published style sheet; we only use it internally for our demos. My thinking is that you'd want to fork this and tweak it. cc @rowanc1
@agoose77 , this is great! Any chance you can add an example with a LaTeX equation?
So (again), there might be a better way, but here's a start.
You can load KaTeX and massage the equations to be picked up by KaTeX's auto renderer:
import { unified } from 'unified'
import { mystParser } from 'myst-parser'
import rehypeDocument from 'rehype-document'
import { State, transform, mystToHast, formatHtml } from 'myst-to-html'
import rehypeStringify from 'rehype-stringify'
import mystToMd from 'myst-to-md';
import { selectAll } from 'unist-util-select';
// Prepare math for KaTeX auto renderer by wrapping in `$$`
function mathTransform(tree, file, opts) {
const inlineNodes = selectAll('inlineMath', tree);
inlineNodes.forEach((node) => {
node.value = `$${node.value}$`
});
const displayNodes = selectAll('math', tree);
displayNodes.forEach((node) => {
node.value = `$$${node.value}$$`
});
}
const mathPlugin =
(opts) => (tree, file) => {
mathTransform(tree, file, opts);
};
// Create a AST document, or parse using mystmd
const pipe = unified()
.use(mystParser)
.use(transform, new State())
.use(mathPlugin)
.use(mystToHast)
.use(formatHtml)
// Load KaTeX
.use(rehypeDocument, {
css: ['myst.css', 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css'],
js: ["https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js", "https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"],
script: `document.addEventListener("DOMContentLoaded", (event) => {
renderMathInElement(document.body, {
delimiters: [{
left: "$$",
right: "$$",
display: true
},
{
left: "$",
right: "$",
display: false
}
]
});
});`
})
.use(rehypeStringify);
// Demo
const result = pipe.processSync(`
:::{important}
Hello to the world!
:::
The math says {math}\`x + y \\frac{x}{y}\`
`);
console.log(result.value);
You don't have to use KaTeX, but I just knew it would be easy to get up and running with it.
Thanks @agoose77 ! This is great! I made some tweaks (see below) to make it a standalone HTML file. FYI, it doesn't look like the table alignment is working, but I believe this is a known issue: https://github.com/executablebooks/mystmd/issues/238
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="myst.css">
<link rel="stylesheet" type="text/css" href='https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css'>
</head>
<div id="output"></div>
<script type="module">
import { unified } from 'https://esm.sh/unified@10.1.2?bundle';
import { mystParser } from 'https://esm.sh/myst-parser@1.0.21?bundle';
import { State, transform, mystToHast, formatHtml } from 'https://esm.sh/myst-to-html@1.0.21?bundle';
import rehypeStringify from 'https://esm.sh/rehype-stringify@9.0.3?bundle';
import { selectAll } from 'https://esm.sh/unist-util-select@5.1.0?bundle';
import renderMathInElement from "https://esm.sh/katex@0.16.9/dist/contrib/auto-render.mjs";
// Prepare math for KaTeX auto renderer by wrapping in `$$`
function mathTransform(tree, file, opts) {
const inlineNodes = selectAll('inlineMath', tree);
inlineNodes.forEach((node) => {
node.value = `$${node.value}$`
});
const displayNodes = selectAll('math', tree);
displayNodes.forEach((node) => {
node.value = `$$${node.value}$$`
});
}
const mathPlugin =
(opts) => (tree, file) => {
mathTransform(tree, file, opts);
};
// Create a AST document, or parse using mystmd
const pipe = unified()
.use(mystParser)
.use(transform, new State())
.use(mathPlugin)
.use(mystToHast)
.use(formatHtml)
// Load KaTeX
.use(rehypeStringify);
// Demo
const result = pipe.processSync(`
# Myst Example
:::{important}
Hello to the world!
:::
| left | center | right |
| :--- | :----: | ----: |
| a | b | c |
:::{figure} https://source.unsplash.com/random/500x200/?mountain
:name: my-fig
:align: center
My **bold** mountain 🏔🚠.
:::
The math says $x^2 + \\big( y \\frac{x}{y} \\big)$
`);
document.getElementById('output').innerHTML = result.value;
// console.log(result.value);
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body, {
// customised options
// • auto-render specific keys, e.g.:
delimiters: [
{ left: '$$', right: '$$', display: true },
{ left: '$', right: '$', display: false },
{ left: '\\(', right: '\\)', display: false },
{ left: '\\[', right: '\\]', display: true }
],
// • rendering keys, e.g.:
throwOnError: false
});
});
</script>
</body>
</html>
I asked here another follow up question: How to resolve relative links?
@fhg-isi , I think for something sophisticated involving multiple markdown documents you may want to use the myst
cli's build
command to convert all the necessary files to a website as described here: https://mystmd.org/guide/quickstart-myst-websites . My example was more for an edge case where I wanted to dynamically incorporate some simple MyST-flavoured Markdown into a pre-existing webpage.
If you can't use the myst
cli for some reason, I'm sure that what you want to do is possible, but I think it's probably more of a unified / remark question than a MyST question (although mine certainly was, too, so please excuse my hypocrisy).
Thank you. Solved it using regular expressions, see https://github.com/orgs/executablebooks/discussions/1125
If I try to use the html example given at
https://github.com/executablebooks/mystmd/tree/main/packages/myst-parser
I get the error
Uncaught ReferenceError: unified is not defined
a) Could you please give a full example on how to use myst-parser in the browser to generate html from myst markdown string?
b) Also see https://stackoverflow.com/questions/77707969/how-to-use-myst-parser-for-sharepoint-web-part