2023-07-31 07:34:36 -05:00
|
|
|
import MarkdownItClass from 'markdown-it'
|
2024-02-23 01:33:01 -06:00
|
|
|
// 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'
|
2023-07-31 07:34:36 -05:00
|
|
|
import sanitizeHtml from 'sanitize-html'
|
|
|
|
import { getDefaultSanitizeOptions, getTextOnlySanitizeOptions, TEXT_WITH_HTML_RULES } from '@peertube/peertube-core-utils'
|
2021-05-27 08:59:55 -05:00
|
|
|
|
2022-02-04 03:31:54 -06:00
|
|
|
const defaultSanitizeOptions = getDefaultSanitizeOptions()
|
|
|
|
const textOnlySanitizeOptions = getTextOnlySanitizeOptions()
|
2021-04-11 08:06:36 -05:00
|
|
|
|
2022-03-07 04:48:53 -06: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)
|
2021-04-11 08:06:36 -05:00
|
|
|
|
2022-01-31 03:07:38 -06:00
|
|
|
const toSafeHtml = (text: string) => {
|
2021-04-16 00:41:35 -05:00
|
|
|
if (!text) return ''
|
|
|
|
|
2021-04-11 08:06:36 -05:00
|
|
|
// Restore line feed
|
|
|
|
const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n')
|
|
|
|
|
|
|
|
// Convert possible markdown (emojis, emphasis and lists) to html
|
2022-03-07 04:48:53 -06:00
|
|
|
const html = markdownItForSafeHtml.render(textWithLineFeed)
|
2021-04-11 08:06:36 -05:00
|
|
|
|
|
|
|
// Convert to safe Html
|
2022-02-04 03:31:54 -06:00
|
|
|
return sanitizeHtml(html, defaultSanitizeOptions)
|
2021-04-11 08:06:36 -05:00
|
|
|
}
|
|
|
|
|
2022-02-04 03:31:54 -06:00
|
|
|
const mdToOneLinePlainText = (text: string) => {
|
2021-04-16 00:41:35 -05:00
|
|
|
if (!text) return ''
|
|
|
|
|
2022-03-07 04:48:53 -06:00
|
|
|
markdownItForPlainText.render(text)
|
2021-04-12 04:43:29 -05:00
|
|
|
|
|
|
|
// Convert to safe Html
|
2022-03-07 04:48:53 -06:00
|
|
|
return sanitizeHtml(markdownItForPlainText.plainText, textOnlySanitizeOptions)
|
2021-04-12 04:43:29 -05:00
|
|
|
}
|
|
|
|
|
2021-04-11 08:06:36 -05:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
export {
|
2021-04-12 04:43:29 -05:00
|
|
|
toSafeHtml,
|
2022-02-04 03:31:54 -06: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 04:48:53 -06:00
|
|
|
markdownIt.plainText = text
|
2022-02-04 03:31:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
function scan (tokens: any[]) {
|
2022-03-07 04:48:53 -06:00
|
|
|
let lastSeparator = ''
|
2022-02-04 03:31:54 -06:00
|
|
|
let text = ''
|
|
|
|
|
2022-03-07 04:48:53 -06:00
|
|
|
function buildSeparator (token: any) {
|
2022-02-04 03:31:54 -06:00
|
|
|
if (token.type === 'list_item_close') {
|
|
|
|
lastSeparator = ', '
|
2022-03-07 04:48:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (token.tag === 'br' || token.type === 'paragraph_close') {
|
2022-02-04 03:31:54 -06:00
|
|
|
lastSeparator = ' '
|
2022-03-07 04:48:53 -06: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 03:31:54 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return text
|
|
|
|
}
|
|
|
|
|
|
|
|
markdownIt.core.ruler.push('plainText', plainTextRule)
|
2021-04-11 08:06:36 -05:00
|
|
|
}
|