UNPKG

@flanksource/clicky-ui

Version:

Flanksource Clicky UI — React component library built on shadcn/ui with light/dark and density theming.

60 lines (59 loc) 2.75 kB
import { jsx } from "react/jsx-runtime"; import { useState, useEffect } from "react"; import { cn } from "../lib/utils.js"; let loadPromise = null; function loadMarked() { if (loadPromise) return loadPromise; loadPromise = import("marked").then(({ Marked, Renderer }) => { const renderer = new Renderer(); renderer.code = ({ text, lang }) => `<pre class="bg-muted rounded p-2 text-xs overflow-x-auto border border-border my-1.5"><code${lang ? ` class="language-${lang}"` : ""}>${text}</code></pre>`; renderer.codespan = ({ text }) => `<code class="bg-muted rounded px-1 text-xs">${text}</code>`; renderer.heading = ({ text, depth }) => { const cls = depth <= 1 ? "font-bold text-base mt-2 mb-1" : depth === 2 ? "font-semibold text-sm mt-2 mb-1" : "font-semibold text-sm mt-2 mb-1"; return `<h${depth} class="${cls}">${text}</h${depth}>`; }; renderer.link = ({ href, text }) => `<a href="${href}" target="_blank" rel="noopener noreferrer" class="text-primary hover:underline">${text}</a>`; renderer.blockquote = ({ text }) => `<blockquote class="border-l-2 border-border pl-2 text-muted-foreground italic my-1">${text}</blockquote>`; renderer.tablerow = ({ text }) => `<tr class="border-b border-border">${text}</tr>`; renderer.list = function(token) { const tag = token.ordered ? "ol" : "ul"; const cls = token.ordered ? "list-decimal ml-4 my-1" : "list-disc ml-4 my-1"; const body = token.items.map((item) => this.listitem(item)).join(""); return `<${tag} class="${cls}">${body}</${tag}>`; }; renderer.listitem = ({ text }) => `<li class="my-0.5">${text}</li>`; renderer.image = ({ href, text }) => `<img src="${href}" alt="${text}" class="max-w-full rounded my-1" />`; renderer.hr = () => '<hr class="border-border my-2" />'; renderer.paragraph = ({ text }) => `<p class="mt-1.5">${text}</p>`; return new Marked({ renderer, gfm: true, breaks: true }); }); return loadPromise; } function Markdown({ text, className }) { const [html, setHtml] = useState(null); useEffect(() => { let cancelled = false; loadMarked().then((m) => Promise.resolve(m.parse(text))).then((out) => { if (!cancelled) setHtml(out); }).catch(() => { if (!cancelled) setHtml(text); }); return () => { cancelled = true; }; }, [text]); if (html === null) { return /* @__PURE__ */ jsx("pre", { className: cn("text-sm whitespace-pre-wrap", className), children: text }); } return /* @__PURE__ */ jsx( "div", { className: cn("prose prose-sm max-w-none dark:prose-invert", className), dangerouslySetInnerHTML: { __html: html } } ); } export { Markdown }; //# sourceMappingURL=Markdown.js.map