on 4fdc19d help sign in
urbit.org/components/Markdown.js
61 lines 1.6 kB history raw
1import remark from "remark";
2import gfm from "remark-gfm";
3import slug from "remark-slug";
4import heading from "remark-heading-id";
5import remarkprism from "remark-prism";
6import normalize from "mdurl/encode";
7import merge from "deepmerge";
8import github from "hast-util-sanitize/lib/github";
9import remarkParse from "remark-parse";
10import remarkRehype from "remark-rehype";
11import rehypeStringify from "rehype-stringify";
12import rehypeRaw from "rehype-raw";
14// img is wrapped in figure so that images can be extra wide in the blog posts
15function Img(h, node) {
16 var props = { src: normalize(node.url), alt: node.alt };
17 if (node.title !== null && node.title !== undefined) {
18 props.title = node.title;
19 }
20 return {
21 type: "element",
22 tagName: "figure",
23 properties: {},
24 children: [
25 {
26 type: "element",
27 tagName: "img",
28 properties: props,
29 },
30 ],
31 };
34const options = {
35 handlers: {
36 image: Img,
37 },
38 sanitize: merge(github, {
39 // remove user-content from github.json to remark-slug work as expected
40 clobberPrefix: "",
41 attributes: { "*": ["className"] },
42 }),
43};
45// Converts markdown strings into markdown HTML/React components
46export default async function Markdown({ post }, disablePlugins) {
47 const result = await remark()
48 .use(remarkParse, options)
49 .use(remarkprism, {
50 plugins: !disablePlugins ? ["show-invisibles"] : [],
51 })
52 .use(gfm)
53 .use(slug)
54 .use(heading)
55 .use(remarkRehype, { allowDangerousHtml: true })
56 .use(rehypeRaw)
57 .use(rehypeStringify)
58 .process(post.content);
60 return result.toString();