rehype-lit
v0.1.11
Published
Lit directive to render markdown. Similar to [rehype-react](https://github.com/rehypejs/rehype-react) or [react-markdown](https://github.com/remarkjs/react-markdown).
Downloads
47
Readme
Rehype Lit
Lit directive to render markdown. Similar to rehype-react or react-markdown.
Features
- [x] safe by default (no dagenrous
unsafeHtml
vurnerable to XSS attacks) - [x] customizeable (pass your own redering functions instead of
<h2>
for## hi
) - [x] plugins
- [x] compliant (100% to CommonMark compliant)
Usage
$ npm i rehype-lit
import { renderMarkdown } from "rehype-lit";
class MyElement extends LitElement {
render() {
const markdown = `# Hello **World**`;
// …
return html`<div>${renderMarkdown(markdown)}</div>`;
// returns: <div><h1>Hello <strong>World</strong></div>
}
}
Here is an example that shows how to use a plugin (remark-gfm, which adds support for footnotes, strikethrough, tables, tasklists and URLs directly):
import { renderMarkdown } from "rehype-lit";
import remarkGfm from "remark-gfm";
const markdown = `
Todo:
- [ ] todo
- [x] done
A table:
| a | b |
| - | - |
`;
class MyElement extends LitElement {
render() {
// …
return html`<div>${renderMarkdown(markdown, [remarkGfm])}</div>`;
}
}
Use with plugin options
This example shows how to use a plugin and give it options. To do that, use an array with the plugin at the first place, and the options second. remark-gfm has an option to allow only double tildes for strikethrough:
import { renderMarkdown } from "rehype-lit";
import remarkGfm from "remark-gfm";
const markdown = "This ~is not~ strikethrough, but ~~this is~~!";
class MyElement extends LitElement {
render() {
// …
return html`<div>
${renderMarkdown(markdown, [[remarkGfm, { singleTilde: false }]])}
</div>`;
}
}
Customize Html Rendering
You can change how elements are rendered extending LitHastRenderer
.
The first generic argument of LitHastRenderer
denotes a type map of tagName
to expected hast
Node type, which is usually Element
:
import { renderMarkdown, LitHastRenderer } from "rehype-lit";
class MyRenderer extends LitHastRenderer<{ h2: Element }, {}> {
constructor() {
super(
{
h2: (node: Element) =>
html`<h2 style="color: red">${this.renderChildren(node)}</h2>`,
},
{}
);
}
}
const myRenderer = new MyRenderer();
class MyElement extends LitElement {
render() {
const markdown = `## Hello, I'm red`;
// …
return html`<div>${renderMarkdown(markdown, [], [], {}, myRenderer)}</div>`;
}
}
Custom AST Nodes
Sometimes you might prefer to to the markdown to TemplateResult
translation yourself. In that case, you can also instruct remarkRehype
to passThrough
some Markdown AST elements to your LitHastRenderer
. In that case you'll need to provide a Typemap from the node.type
to its Markdown AST Node Type. (E.g. from leafDirective
to LeafDirective
):
import { renderMarkdown, LitHastRenderer } from "rehype-lit";
class MyRenderer extends LitHastRenderer<{}, { leafDirective: LeafDirective }> {
constructor() {
super(
{},
{
leafDirective: (node) => {
if (node.name === "button") {
return html`<button>${this.renderChildren(node)}</button>`;
}
return html`<div>Unknown directive: ${node.name}</div>`;
},
}
);
}
}
const myRenderer = new MyRenderer();
class MyElement extends LitElement {
render() {
const markdown = `::button[i'm displayed as a button]`;
// …
return html`<div>${renderMarkdown(
markdown,
[remarkDirective],
[],
{ passThrough: ["leafDirective"] },
myRenderer
)}</div>`;
}
}
Advanced use-cases
See example and try it out by using pnpm run dev
The following diagram show, where the arguments to renderMarkdown
are plugged into the unified
pipeline:
Acknowledgements
- The README and API is heavily inspired by
react-markdown
unified
remark
andrehype
infrastructure, which makes this easy.