PeerTube/server/core/helpers/markdown.ts

90 lines
2.4 KiB
TypeScript
Raw Normal View History

import MarkdownItClass from 'markdown-it'
import markdownItEmoji from 'markdown-it-emoji/light.js'
import sanitizeHtml from 'sanitize-html'
import { getDefaultSanitizeOptions, getTextOnlySanitizeOptions, TEXT_WITH_HTML_RULES } from '@peertube/peertube-core-utils'
2022-02-04 10:31:54 +01:00
const defaultSanitizeOptions = getDefaultSanitizeOptions()
const textOnlySanitizeOptions = getTextOnlySanitizeOptions()
2022-03-07 11:48:53 +01:00
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) => {
2021-04-16 07:41:35 +02:00
if (!text) return ''
// Restore line feed
const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n')
// Convert possible markdown (emojis, emphasis and lists) to html
2022-03-07 11:48:53 +01:00
const html = markdownItForSafeHtml.render(textWithLineFeed)
// Convert to safe Html
2022-02-04 10:31:54 +01:00
return sanitizeHtml(html, defaultSanitizeOptions)
}
2022-02-04 10:31:54 +01:00
const mdToOneLinePlainText = (text: string) => {
2021-04-16 07:41:35 +02:00
if (!text) return ''
2022-03-07 11:48:53 +01:00
markdownItForPlainText.render(text)
// Convert to safe Html
2022-03-07 11:48:53 +01:00
return sanitizeHtml(markdownItForPlainText.plainText, textOnlySanitizeOptions)
}
// ---------------------------------------------------------------------------
export {
toSafeHtml,
2022-02-04 10:31:54 +01:00
mdToOneLinePlainText
}
// ---------------------------------------------------------------------------
// Thanks: https://github.com/wavesheep/markdown-it-plain-text
function plainTextPlugin (markdownIt: any) {
function plainTextRule (state: any) {
const text = scan(state.tokens)
2022-03-07 11:48:53 +01:00
markdownIt.plainText = text
2022-02-04 10:31:54 +01:00
}
function scan (tokens: any[]) {
2022-03-07 11:48:53 +01:00
let lastSeparator = ''
2022-02-04 10:31:54 +01:00
let text = ''
2022-03-07 11:48:53 +01:00
function buildSeparator (token: any) {
2022-02-04 10:31:54 +01:00
if (token.type === 'list_item_close') {
lastSeparator = ', '
2022-03-07 11:48:53 +01:00
}
if (token.tag === 'br' || token.type === 'paragraph_close') {
2022-02-04 10:31:54 +01:00
lastSeparator = ' '
2022-03-07 11:48:53 +01:00
}
}
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 = ''
2022-02-04 10:31:54 +01:00
}
}
return text
}
markdownIt.core.ruler.push('plainText', plainTextRule)
}