From 2844c8bc25e4b36b64a68bc42a0227462bd4785d Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Thu, 2 Nov 2023 12:35:30 +0100 Subject: [PATCH] Markdown plug APIS --- plugs/markdown/api.ts | 66 +++++++++++++++++++++++++++++++ plugs/markdown/markdown.plug.yaml | 5 ++- plugs/markdown/markdown_render.ts | 2 +- 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 plugs/markdown/api.ts diff --git a/plugs/markdown/api.ts b/plugs/markdown/api.ts new file mode 100644 index 00000000..7f7fb449 --- /dev/null +++ b/plugs/markdown/api.ts @@ -0,0 +1,66 @@ +import { + findNodeOfType, + ParseTree, + renderToText, + replaceNodesMatchingAsync, +} from "$sb/lib/tree.ts"; +import { codeWidget } from "$sb/syscalls.ts"; +import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts"; +import { + MarkdownRenderOptions, + renderMarkdownToHtml, +} from "./markdown_render.ts"; + +/** + * Finds code widgets, runs their plug code to render and inlines their content in the parse tree + * @param mdTree parsed markdown tree + * @param pageName name of the current page + * @returns modified mdTree + */ +export async function expandCodeWidgets( + mdTree: ParseTree, + pageName: string, +): Promise { + await replaceNodesMatchingAsync(mdTree, async (n) => { + if (n.type === "FencedCode") { + const codeInfo = findNodeOfType(n, "CodeInfo"); + if (!codeInfo) { + return; + } + const codeType = codeInfo.children![0].text!; + const codeTextNode = findNodeOfType(n, "CodeText"); + try { + // This will error out if this is not a code wiget, which is fine + const result = await codeWidget.render( + codeType, + renderToText(codeTextNode!), + pageName, + ); + // Only do this for "markdown" widgets, that is: that can render to markdown + if (result.markdown) { + const parsedBody = await parseMarkdown(result.markdown); + // Recursively process + return expandCodeWidgets( + parsedBody, + pageName, + ); + } + } catch (e: any) { + // 'not found' is to be expected (no code widget configured for this language) + // Every other error should probably be reported + if (!e.message.includes("not found")) { + console.error("Error rendering code", e.message); + } + } + } + }); + return mdTree; +} + +export async function markdownToHtml( + markdown: string, + options: MarkdownRenderOptions = {}, +) { + const mdTree = await parseMarkdown(markdown); + return renderMarkdownToHtml(mdTree, options); +} diff --git a/plugs/markdown/markdown.plug.yaml b/plugs/markdown/markdown.plug.yaml index b7178963..b9cfeb53 100644 --- a/plugs/markdown/markdown.plug.yaml +++ b/plugs/markdown/markdown.plug.yaml @@ -2,10 +2,13 @@ name: markdown assets: - "assets/*" functions: - # API markdownContentWidget: path: markdown_content_widget.ts:markdownContentWidget + expandCodeWidgets: + path: api.ts:expandCodeWidgets + markdownToHtml: + path: api.ts:markdownToHtml # User facing diff --git a/plugs/markdown/markdown_render.ts b/plugs/markdown/markdown_render.ts index 2095ab85..2d8d6e44 100644 --- a/plugs/markdown/markdown_render.ts +++ b/plugs/markdown/markdown_render.ts @@ -8,7 +8,7 @@ import { } from "$sb/lib/tree.ts"; import { Fragment, renderHtml, Tag } from "./html_render.ts"; -type MarkdownRenderOptions = { +export type MarkdownRenderOptions = { failOnUnknown?: true; smartHardBreak?: true; annotationPositions?: true;