aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers/markdown.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/helpers/markdown.ts')
-rw-r--r--server/helpers/markdown.ts68
1 files changed, 52 insertions, 16 deletions
diff --git a/server/helpers/markdown.ts b/server/helpers/markdown.ts
index 0b8c2fabc..25685ec6d 100644
--- a/server/helpers/markdown.ts
+++ b/server/helpers/markdown.ts
@@ -1,14 +1,14 @@
1import { getSanitizeOptions, TEXT_WITH_HTML_RULES } from '@shared/core-utils' 1import { getDefaultSanitizeOptions, getTextOnlySanitizeOptions, TEXT_WITH_HTML_RULES } from '@shared/core-utils'
2 2
3const sanitizeOptions = getSanitizeOptions() 3const defaultSanitizeOptions = getDefaultSanitizeOptions()
4const textOnlySanitizeOptions = getTextOnlySanitizeOptions()
4 5
5const sanitizeHtml = require('sanitize-html') 6const sanitizeHtml = require('sanitize-html')
6const markdownItEmoji = require('markdown-it-emoji/light') 7const markdownItEmoji = require('markdown-it-emoji/light')
7const MarkdownItClass = require('markdown-it') 8const MarkdownItClass = require('markdown-it')
8const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
9 9
10markdownIt.enable(TEXT_WITH_HTML_RULES) 10const markdownItWithHTML = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
11markdownIt.use(markdownItEmoji) 11const markdownItWithoutHTML = new MarkdownItClass('default', { linkify: true, breaks: true, html: false })
12 12
13const toSafeHtml = (text: string) => { 13const toSafeHtml = (text: string) => {
14 if (!text) return '' 14 if (!text) return ''
@@ -17,29 +17,65 @@ const toSafeHtml = (text: string) => {
17 const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n') 17 const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n')
18 18
19 // Convert possible markdown (emojis, emphasis and lists) to html 19 // Convert possible markdown (emojis, emphasis and lists) to html
20 const html = markdownIt.render(textWithLineFeed) 20 const html = markdownItWithHTML.enable(TEXT_WITH_HTML_RULES)
21 .use(markdownItEmoji)
22 .render(textWithLineFeed)
21 23
22 // Convert to safe Html 24 // Convert to safe Html
23 return sanitizeHtml(html, sanitizeOptions) 25 return sanitizeHtml(html, defaultSanitizeOptions)
24} 26}
25 27
26const mdToPlainText = (text: string) => { 28const mdToOneLinePlainText = (text: string) => {
27 if (!text) return '' 29 if (!text) return ''
28 30
29 // Convert possible markdown (emojis, emphasis and lists) to html 31 markdownItWithoutHTML.use(markdownItEmoji)
30 const html = markdownIt.render(text) 32 .use(plainTextPlugin)
33 .render(text)
31 34
32 // Convert to safe Html 35 // Convert to safe Html
33 const safeHtml = sanitizeHtml(html, sanitizeOptions) 36 return sanitizeHtml(markdownItWithoutHTML.plainText, textOnlySanitizeOptions)
34
35 return safeHtml.replace(/<[^>]+>/g, '')
36 .replace(/\n$/, '')
37 .replace(/\n/g, ', ')
38} 37}
39 38
40// --------------------------------------------------------------------------- 39// ---------------------------------------------------------------------------
41 40
42export { 41export {
43 toSafeHtml, 42 toSafeHtml,
44 mdToPlainText 43 mdToOneLinePlainText
44}
45
46// ---------------------------------------------------------------------------
47
48// Thanks: https://github.com/wavesheep/markdown-it-plain-text
49function plainTextPlugin (markdownIt: any) {
50 let lastSeparator = ''
51
52 function plainTextRule (state: any) {
53 const text = scan(state.tokens)
54
55 markdownIt.plainText = text.replace(/\s+/g, ' ')
56 }
57
58 function scan (tokens: any[]) {
59 let text = ''
60
61 for (const token of tokens) {
62 if (token.children !== null) {
63 text += scan(token.children)
64 continue
65 }
66
67 if (token.type === 'list_item_close') {
68 lastSeparator = ', '
69 } else if (/[a-zA-Z]+_close/.test(token.type)) {
70 lastSeparator = ' '
71 } else if (token.content) {
72 text += lastSeparator
73 text += token.content
74 }
75 }
76
77 return text
78 }
79
80 markdownIt.core.ruler.push('plainText', plainTextRule)
45} 81}