"use strict"; import { parse, Renderer, type Tokens } from "marked"; import htmlSanitizer from "../html_sanitizer.js"; import importUtils from "./utils.js"; import { getMimeTypeFromMarkdownName, MIME_TYPE_AUTO } from "@triliumnext/commons"; import { ADMONITION_TYPE_MAPPINGS } from "../export/markdown.js"; import utils from "../utils.js"; import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons"; /** * Keep renderer code up to date with https://github.com/markedjs/marked/blob/master/src/Renderer.ts. */ class CustomMarkdownRenderer extends Renderer { heading(data: Tokens.Heading): string { // Treat h1 as raw text. if (data.depth === 1) { return `
${text}
`;
}
list(token: Tokens.List): string {
let result = super.list(token)
.replace("\n", "") // we replace the first one only.
.trimEnd();
// Handle todo-list in the CKEditor format.
if (token.items.some(item => item.task)) {
result = result.replace(/^\[\!([A-Z]+)\]/.exec(body); if (Array.isArray(admonitionMatch) && admonitionMatch.length === 2) { const type = admonitionMatch[1].toLowerCase(); if (ADMONITION_TYPE_MAPPINGS[type]) { const bodyWithoutHeader = body .replace(/^
\[\!([A-Z]+)\]\s*/, "
") .replace(/^
<\/p>/, ""); // Having a heading will generate an empty paragraph that we need to remove. return ``; } } return `
${body}`; } } function renderToHtml(content: string, title: string) { // Double-escape slashes in math expression because they are otherwise consumed by the parser somewhere. content = content.replaceAll("\\$", "\\\\$"); let html = parse(content, { async: false, renderer: renderer }) as string; // h1 handling needs to come before sanitization html = importUtils.handleH1(html, title); html = htmlSanitizer.sanitize(html); // Add a trailing semicolon to CSS styles. html = html.replaceAll(/(<(img|figure|col).*?style=".*?)"/g, "$1;\""); // Remove slash for self-closing tags to match CKEditor's approach. html = html.replace(/<(\w+)([^>]*)\s+\/>/g, "<$1$2>"); // Normalize non-breaking spaces to entity. html = html.replaceAll("\u00a0", " "); return html; } function getNormalizedMimeFromMarkdownLanguage(language: string | undefined) { if (language) { const mimeDefinition = getMimeTypeFromMarkdownName(language); if (mimeDefinition) { return normalizeMimeTypeForCKEditor(mimeDefinition.mime); } } return MIME_TYPE_AUTO; } const renderer = new CustomMarkdownRenderer({ async: false }); export default { renderToHtml };