PeerTube/server/helpers/markdown.ts

82 lines
2.3 KiB
TypeScript
Raw Normal View History

2022-02-04 03:31:54 -06:00
import { getDefaultSanitizeOptions, getTextOnlySanitizeOptions, TEXT_WITH_HTML_RULES } from '@shared/core-utils'
2022-02-04 03:31:54 -06:00
const defaultSanitizeOptions = getDefaultSanitizeOptions()
const textOnlySanitizeOptions = getTextOnlySanitizeOptions()
const sanitizeHtml = require('sanitize-html')
const markdownItEmoji = require('markdown-it-emoji/light')
const MarkdownItClass = require('markdown-it')
2022-02-04 03:31:54 -06:00
const markdownItWithHTML = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
const markdownItWithoutHTML = new MarkdownItClass('default', { linkify: true, breaks: true, html: false })
const toSafeHtml = (text: string) => {
2021-04-16 00:41:35 -05: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-02-04 03:31:54 -06:00
const html = markdownItWithHTML.enable(TEXT_WITH_HTML_RULES)
.use(markdownItEmoji)
.render(textWithLineFeed)
// Convert to safe Html
2022-02-04 03:31:54 -06:00
return sanitizeHtml(html, defaultSanitizeOptions)
}
2022-02-04 03:31:54 -06:00
const mdToOneLinePlainText = (text: string) => {
2021-04-16 00:41:35 -05:00
if (!text) return ''
2022-02-04 03:31:54 -06:00
markdownItWithoutHTML.use(markdownItEmoji)
.use(plainTextPlugin)
.render(text)
// Convert to safe Html
2022-02-04 03:31:54 -06:00
return sanitizeHtml(markdownItWithoutHTML.plainText, textOnlySanitizeOptions)
}
// ---------------------------------------------------------------------------
export {
toSafeHtml,
2022-02-04 03:31:54 -06:00
mdToOneLinePlainText
}
// ---------------------------------------------------------------------------
// Thanks: https://github.com/wavesheep/markdown-it-plain-text
function plainTextPlugin (markdownIt: any) {
let lastSeparator = ''
function plainTextRule (state: any) {
const text = scan(state.tokens)
markdownIt.plainText = text.replace(/\s+/g, ' ')
}
function scan (tokens: any[]) {
let text = ''
for (const token of tokens) {
if (token.children !== null) {
text += scan(token.children)
continue
}
if (token.type === 'list_item_close') {
lastSeparator = ', '
} else if (/[a-zA-Z]+_close/.test(token.type)) {
lastSeparator = ' '
} else if (token.content) {
text += lastSeparator
text += token.content
}
}
return text
}
markdownIt.core.ruler.push('plainText', plainTextRule)
}