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).
Readme
Rehype Lit
Lit directive to render markdown. Similar to rehype-react or react-markdown.
Features
- [x] safe by default (no dagenrous
unsafeHtmlvurnerable 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-litimport { 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 unifiedremarkandrehypeinfrastructure, which makes this easy.
