Files
plainleaf/client/components/plainleaf_markdown_preview.ts
wushenghuaandCodex becc6694c2 feat: 完善云叶冒险皮肤与笔记体验
统一登录、工作区、待办、设置和管理页面的视觉语言,补充 Markdown 预览、皮肤切换及移动端体验。

Co-Authored-By: Codex <noreply@anthropic.com>
2026-08-13 09:44:30 +08:00

55 lines
1.6 KiB
TypeScript

import DOMPurify from "dompurify";
import type { PageMeta } from "@silverbulletmd/silverbullet/type/index";
import { encodePageURI } from "@silverbulletmd/silverbullet/lib/ref";
import {
isLocalURL,
resolveMarkdownLink,
} from "@silverbulletmd/silverbullet/lib/resolve";
import { parseMarkdown } from "../markdown_parser/parser.ts";
import { renderMarkdownToHtml } from "../markdown_renderer/markdown_render.ts";
import { fsEndpoint } from "../spaces/constants.ts";
type Sanitize = (html: string) => string;
export function resolvePlainleafPreviewUrl(
currentPage: string,
baseUrl: string,
url: string,
type: "link" | "image",
): string {
if (!isLocalURL(url)) return url;
const mediaPrefix = `${fsEndpoint.slice(1)}/`;
const sourceUrl =
type === "image" && url.startsWith(mediaPrefix)
? url.slice(mediaPrefix.length)
: url;
const path = resolveMarkdownLink(currentPage, decodeURI(sourceUrl));
if (type === "image") {
return `${baseUrl.replace(/\/*$/, "")}${fsEndpoint}/${encodePageURI(path)}`;
}
return path;
}
export function renderPlainleafMarkdownPreview(
text: string,
allPages: PageMeta[],
translateUrls: (url: string, type: "link" | "image") => string,
sanitize: Sanitize = (html) =>
DOMPurify.sanitize(html, {
USE_PROFILES: { html: true },
FORBID_TAGS: ["script", "style", "iframe", "object", "embed"],
FORBID_ATTR: ["srcdoc"],
}),
): string {
const html = renderMarkdownToHtml(
parseMarkdown(text),
{
smartHardBreak: true,
shortWikiLinks: true,
translateUrls,
},
allPages,
);
return sanitize(html);
}