import MarkdownItClass from 'markdown-it' // FIXME: use direct import: import markdownItEmoji from 'markdown-it-emoji/lib/light.mjs' if it improves perf' // when https://github.com/privatenumber/tsx/issues/334 is fixed import { light as markdownItEmoji } from 'markdown-it-emoji' import sanitizeHtml from 'sanitize-html' import { getDefaultSanitizeOptions, getTextOnlySanitizeOptions, TEXT_WITH_HTML_RULES } from '@peertube/peertube-core-utils' const defaultSanitizeOptions = getDefaultSanitizeOptions() const textOnlySanitizeOptions = getTextOnlySanitizeOptions() const markdownItForSafeHtml = new MarkdownItClass('default', { linkify: true, breaks: true, html: true }) .enable(TEXT_WITH_HTML_RULES) .use(markdownItEmoji) const markdownItForPlainText = new MarkdownItClass('default', { linkify: false, breaks: true, html: false }) .use(markdownItEmoji) .use(plainTextPlugin) const toSafeHtml = (text: string) => { if (!text) return '' // Restore line feed const textWithLineFeed = text.replace(//g, '\r\n') // Convert possible markdown (emojis, emphasis and lists) to html const html = markdownItForSafeHtml.render(textWithLineFeed) // Convert to safe Html return sanitizeHtml(html, defaultSanitizeOptions) } const mdToOneLinePlainText = (text: string) => { if (!text) return '' markdownItForPlainText.render(text) // Convert to safe Html return sanitizeHtml(markdownItForPlainText.plainText, textOnlySanitizeOptions) } // --------------------------------------------------------------------------- export { toSafeHtml, mdToOneLinePlainText } // --------------------------------------------------------------------------- // Thanks: https://github.com/wavesheep/markdown-it-plain-text function plainTextPlugin (markdownIt: any) { function plainTextRule (state: any) { const text = scan(state.tokens) markdownIt.plainText = text } function scan (tokens: any[]) { let lastSeparator = '' let text = '' function buildSeparator (token: any) { if (token.type === 'list_item_close') { lastSeparator = ', ' } if (token.tag === 'br' || token.type === 'paragraph_close') { lastSeparator = ' ' } } for (const token of tokens) { buildSeparator(token) if (token.type !== 'inline') continue for (const child of token.children) { buildSeparator(child) if (!child.content) continue text += lastSeparator + child.content lastSeparator = '' } } return text } markdownIt.core.ruler.push('plainText', plainTextRule) }