73 lines
1.4 KiB
JavaScript
73 lines
1.4 KiB
JavaScript
import DOMPurify from 'dompurify';
|
|
import { marked } from 'marked';
|
|
|
|
marked.setOptions({
|
|
gfm: true,
|
|
breaks: true,
|
|
});
|
|
|
|
const markdownCache = new Map();
|
|
const inlineCache = new Map();
|
|
|
|
function sanitizeHtml(html) {
|
|
return DOMPurify.sanitize(html, {
|
|
USE_PROFILES: { html: true },
|
|
});
|
|
}
|
|
|
|
function toSafeString(value) {
|
|
if (typeof value === 'string') {
|
|
return value.trim();
|
|
}
|
|
if (value === null || value === undefined) {
|
|
return '';
|
|
}
|
|
return String(value).trim();
|
|
}
|
|
|
|
function parseMarkdown(source) {
|
|
const parsed = marked.parse(source);
|
|
if (typeof parsed === 'string') {
|
|
return parsed;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function parseInlineMarkdown(source) {
|
|
const parsed = marked.parseInline(source);
|
|
if (typeof parsed === 'string') {
|
|
return parsed;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
export function renderMarkdown(value) {
|
|
const source = toSafeString(value);
|
|
if (!source) {
|
|
return '';
|
|
}
|
|
|
|
if (markdownCache.has(source)) {
|
|
return markdownCache.get(source);
|
|
}
|
|
|
|
const html = sanitizeHtml(parseMarkdown(source));
|
|
markdownCache.set(source, html);
|
|
return html;
|
|
}
|
|
|
|
export function renderInlineMarkdown(value) {
|
|
const source = toSafeString(value);
|
|
if (!source) {
|
|
return '';
|
|
}
|
|
|
|
if (inlineCache.has(source)) {
|
|
return inlineCache.get(source);
|
|
}
|
|
|
|
const html = sanitizeHtml(parseInlineMarkdown(source));
|
|
inlineCache.set(source, html);
|
|
return html;
|
|
}
|