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
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);
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}${t.name}>`;
}