import * as Mustache from 'mustache'; import { filename } from '@joplin/lib/path-utils'; import * as fs from 'fs-extra'; import { Partials, TemplateParams } from './types'; import { headerAnchor } from '@joplin/renderer'; import * as MarkdownIt from 'markdown-it'; export async function loadMustachePartials(partialDir: string) { const output: Partials = {}; const files = await fs.readdir(partialDir); for (const f of files) { const name = filename(f); const templateContent = await fs.readFile(`${partialDir}/${f}`, 'utf8'); output[name] = templateContent; } return output; } export function renderMustache(contentHtml: string, templateParams: TemplateParams) { return Mustache.render(templateParams.templateHtml, { ...templateParams, contentHtml, }, templateParams.partials); } export function getMarkdownIt() { const markdownIt = new MarkdownIt({ breaks: true, linkify: true, html: true, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied markdownIt.core.ruler.push('tableClass', (state: any) => { const tokens = state.tokens; for (let i = 0; i < tokens.length; i++) { const token = tokens[i]; if (token.type === 'table_open') { token.attrs = [ ['class', 'table'], ]; } } }); return markdownIt; } export function markdownToPageHtml(md: string, templateParams: TemplateParams): string { const html = markdownToHtml(md); return renderMustache(html, templateParams); } export const markdownToHtml = (md: string): string => { const markdownIt = getMarkdownIt(); markdownIt.use(headerAnchor); markdownIt.linkify.set({ 'fuzzyLink': false, 'fuzzyIP': false, 'fuzzyEmail': false, }); return markdownIt.render(md); };