diff options
Diffstat (limited to 'docs/src/app.ffi.mjs')
-rw-r--r-- | docs/src/app.ffi.mjs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/docs/src/app.ffi.mjs b/docs/src/app.ffi.mjs new file mode 100644 index 0000000..f5e7f29 --- /dev/null +++ b/docs/src/app.ffi.mjs @@ -0,0 +1,95 @@ +import { fromMarkdown } from "mdast-util-from-markdown"; +import { attribute } from "../lustre/lustre/attribute.mjs"; +import { element, text } from "../lustre/lustre/element.mjs"; +import { List } from "./gleam.mjs"; +import * as Markdown from "./app/ui/markdown.mjs"; + +// Parsing markdown and then walking the AST is expensive so we're going to trade +// some memory for speed and cache the results. +const cache = new Map(); + +// fn parse_markdown(md: String) -> #(List(Element(msg)), List(Element(msg))) +export const parse_markdown = (md) => { + if (cache.has(md)) return cache.get(md); + + const ast = fromMarkdown(md); + const summary = []; + const content = ast.children.map(function to_lustre_element(node) { + switch (node.type) { + case "code": + return Markdown.code(node.value); + + case "emphasis": + return Markdown.emphasis( + List.fromArray(node.children.map(to_lustre_element)) + ); + + case "heading": { + const [title, rest] = node.children[0].value.split("|"); + const tags = List.fromArray(rest ? rest.trim().split(" ") : []); + const id = + /^[A-Z]/.test(title.trim()) && node.depth === 3 + ? `${title.toLowerCase().trim().replace(/\s/g, "-")}-type` + : `${title.toLowerCase().trim().replace(/\s/g, "-")}`; + + if (node.depth > 1) { + summary.push( + element( + "a", + List.fromArray([ + attribute("href", `#${id}`), + attribute("class", "text-sm text-gray-400 no-underline"), + attribute("class", "hover:text-gray-700 hover:underline"), + attribute( + "class", + node.depth === 2 ? `mt-4 first:mt-0` : `ml-2` + ), + ]), + List.fromArray([text(title.trim())]) + ) + ); + } + + return Markdown.heading(node.depth, title.trim(), tags, id); + } + + case "inlineCode": + return Markdown.inline_code(node.value); + + case "link": + return Markdown.link(node.url, List.fromArray(node.children)); + + case "list": + return Markdown.list( + !!node.ordered, + List.fromArray(node.children.map(to_lustre_element)) + ); + + case "listItem": + return Markdown.list_item( + List.fromArray(node.children.map(to_lustre_element)) + ); + + case "paragraph": + return Markdown.paragraph( + List.fromArray(node.children.map(to_lustre_element)) + ); + + case "strong": + return Markdown.strong( + List.fromArray(node.children.map(to_lustre_element)) + ); + + case "text": + return Markdown.text(node.value); + + default: + return Markdown.text(""); + } + }); + + const result = [List.fromArray(content), List.fromArray(summary)]; + cache.set(md, result); + + return result; +}; |