From 704c2b5f675e09ec401c67b3afc64c1e78a65655 Mon Sep 17 00:00:00 2001 From: Anthony Lawn Date: Tue, 21 Jul 2026 02:26:45 -0500 Subject: [PATCH 1/3] Fix custom code widgets not being able to effect data objects (#2059) Co-authored-by: thepaperpilot --- client/codemirror/fenced_code.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/codemirror/fenced_code.ts b/client/codemirror/fenced_code.ts index 4c227dfd..65b00eba 100644 --- a/client/codemirror/fenced_code.ts +++ b/client/codemirror/fenced_code.ts @@ -24,7 +24,7 @@ export function fencedCodePlugin(client: Client) { return; } const text = state.sliceDoc(from, to); - const [_, lang] = text.match(/^(?:```+|~~~+)(\w+)?/)!; + const [_, lang] = text.match(/^(?:```+|~~~+)(\S+)?/)!; const renderMode = widgetRenderMode(client); const luaWidgetDef = lang From 9676ca85635c480f85756fbb3ad25a7dbda3f550 Mon Sep 17 00:00:00 2001 From: Anthony Lawn Date: Tue, 21 Jul 2026 03:04:55 -0500 Subject: [PATCH 2/3] Fix transclusions of custom syntaxes not closing html tags (#2057) Co-authored-by: thepaperpilot --- client/codemirror/inline_content.ts | 42 +++++++++++++++++++---------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/client/codemirror/inline_content.ts b/client/codemirror/inline_content.ts index a51d5e68..1c61b8e0 100644 --- a/client/codemirror/inline_content.ts +++ b/client/codemirror/inline_content.ts @@ -15,17 +15,20 @@ import { expandMarkdown, readTransclusionContent, } from "../markdown_renderer/inline.ts"; +import { renderMarkdownToHtml } from "../markdown_renderer/markdown_render.ts"; import { isLocalURL, resolveMarkdownLink, } from "@silverbulletmd/silverbullet/lib/resolve"; -import { parseMarkdown } from "../markdown_parser/parser.ts"; +import { buildExtendedMarkdownLanguage } from "../markdown_parser/parser.ts"; +import { parse } from "../markdown_parser/parse_tree.ts"; import { renderToText } from "@silverbulletmd/silverbullet/lib/tree"; import { nameFromTransclusion, parseTransclusion, } from "@silverbulletmd/silverbullet/lib/transclusion"; import { parseToRef } from "@silverbulletmd/silverbullet/lib/ref"; +import { buildTranslateUrls } from "./widget_util.ts"; export function inlineContentPlugin(client: Client) { return decoratorStateField((state: EditorState) => { @@ -97,21 +100,32 @@ export function inlineContentPlugin(client: Client) { client.space, transclusion, ); + const syntaxExtensions = client.config.get( + "syntaxExtensions", + {}, + ); + const mdLang = + buildExtendedMarkdownLanguage(syntaxExtensions); + const expandedTree = await expandMarkdown( + client.space, + nameFromTransclusion(transclusion), + parse(mdLang, result.text, result.offset), + client.clientSystem.spaceLuaEnv, + { syntaxExtensions }, + ); content = { - markdown: renderToText( - await expandMarkdown( - client.space, - nameFromTransclusion(transclusion), - parseMarkdown(result.text, result.offset), - client.clientSystem.spaceLuaEnv, - { - syntaxExtensions: client.config.get( - "syntaxExtensions", - {}, - ), - }, - ), + html: renderMarkdownToHtml( + expandedTree, + { + shortWikiLinks: client.config.get( + "shortWikiLinks", + true, + ), + translateUrls: buildTranslateUrls(client), + }, + client.ui.viewState.allPages, ), + markdown: renderToText(expandedTree), }; } catch { const element = createMediaElement(transclusion); From 594688ba224ae04e8a0dbad5c074e117e05c0883 Mon Sep 17 00:00:00 2001 From: Anthony Lawn Date: Tue, 21 Jul 2026 03:18:39 -0500 Subject: [PATCH 3/3] Fix markdownToHtml including closing tags for void elements (#2056) Co-authored-by: thepaperpilot --- client/markdown_renderer/html_render.test.ts | 23 ++++++++++++++++++++ client/markdown_renderer/html_render.ts | 20 +++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/client/markdown_renderer/html_render.test.ts b/client/markdown_renderer/html_render.test.ts index f0d7c320..e1feb503 100644 --- a/client/markdown_renderer/html_render.test.ts +++ b/client/markdown_renderer/html_render.test.ts @@ -43,6 +43,29 @@ test("RawHtml with array body passes strings through unescaped", () => { ).toEqual("boldnormal"); }); +test("Void elements have no closing tag", () => { + expect( + renderHtml({ + name: "img", + attrs: { src: "test.png", alt: "" }, + body: "", + }), + ).toEqual(''); + expect( + renderHtml({ + name: "IMG", + attrs: { src: "test.png" }, + body: "", + }), + ).toEqual(''); + expect( + renderHtml({ + name: "br", + body: "", + }), + ).toEqual("
"); +}); + test("Fragment renders children without wrapper", () => { expect( renderHtml({ diff --git a/client/markdown_renderer/html_render.ts b/client/markdown_renderer/html_render.ts index 34261803..be0a5fa5 100644 --- a/client/markdown_renderer/html_render.ts +++ b/client/markdown_renderer/html_render.ts @@ -1,6 +1,23 @@ export const Fragment = "FRAGMENT"; export const RawHtml = "RAW_HTML"; +const VOID_ELEMENTS = new Set([ + "area", + "base", + "br", + "col", + "embed", + "hr", + "img", + "input", + "link", + "meta", + "param", + "source", + "track", + "wbr", +]); + export type Tag = | { name: string; @@ -57,5 +74,8 @@ export function renderHtml(t: Tag | null): string { .map((c) => (typeof c === "string" ? c : renderHtml(c))) .join(""); } + if (VOID_ELEMENTS.has(t.name.toLowerCase())) { + return `<${t.name}${attrs}>`; + } return `<${t.name}${attrs}>${body}`; }