diff options
Diffstat (limited to 'server/helpers/markdown.ts')
-rw-r--r-- | server/helpers/markdown.ts | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/server/helpers/markdown.ts b/server/helpers/markdown.ts index 41c1186ec..a20ac22d4 100644 --- a/server/helpers/markdown.ts +++ b/server/helpers/markdown.ts | |||
@@ -7,8 +7,13 @@ const sanitizeHtml = require('sanitize-html') | |||
7 | const markdownItEmoji = require('markdown-it-emoji/light') | 7 | const markdownItEmoji = require('markdown-it-emoji/light') |
8 | const MarkdownItClass = require('markdown-it') | 8 | const MarkdownItClass = require('markdown-it') |
9 | 9 | ||
10 | const markdownItWithHTML = new MarkdownItClass('default', { linkify: true, breaks: true, html: true }) | 10 | const markdownItForSafeHtml = new MarkdownItClass('default', { linkify: true, breaks: true, html: true }) |
11 | const markdownItWithoutHTML = new MarkdownItClass('default', { linkify: false, breaks: true, html: false }) | 11 | .enable(TEXT_WITH_HTML_RULES) |
12 | .use(markdownItEmoji) | ||
13 | |||
14 | const markdownItForPlainText = new MarkdownItClass('default', { linkify: false, breaks: true, html: false }) | ||
15 | .use(markdownItEmoji) | ||
16 | .use(plainTextPlugin) | ||
12 | 17 | ||
13 | const toSafeHtml = (text: string) => { | 18 | const toSafeHtml = (text: string) => { |
14 | if (!text) return '' | 19 | if (!text) return '' |
@@ -17,9 +22,7 @@ const toSafeHtml = (text: string) => { | |||
17 | const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n') | 22 | const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n') |
18 | 23 | ||
19 | // Convert possible markdown (emojis, emphasis and lists) to html | 24 | // Convert possible markdown (emojis, emphasis and lists) to html |
20 | const html = markdownItWithHTML.enable(TEXT_WITH_HTML_RULES) | 25 | const html = markdownItForSafeHtml.render(textWithLineFeed) |
21 | .use(markdownItEmoji) | ||
22 | .render(textWithLineFeed) | ||
23 | 26 | ||
24 | // Convert to safe Html | 27 | // Convert to safe Html |
25 | return sanitizeHtml(html, defaultSanitizeOptions) | 28 | return sanitizeHtml(html, defaultSanitizeOptions) |
@@ -28,12 +31,10 @@ const toSafeHtml = (text: string) => { | |||
28 | const mdToOneLinePlainText = (text: string) => { | 31 | const mdToOneLinePlainText = (text: string) => { |
29 | if (!text) return '' | 32 | if (!text) return '' |
30 | 33 | ||
31 | markdownItWithoutHTML.use(markdownItEmoji) | 34 | markdownItForPlainText.render(text) |
32 | .use(plainTextPlugin) | ||
33 | .render(text) | ||
34 | 35 | ||
35 | // Convert to safe Html | 36 | // Convert to safe Html |
36 | return sanitizeHtml(markdownItWithoutHTML.plainText, textOnlySanitizeOptions) | 37 | return sanitizeHtml(markdownItForPlainText.plainText, textOnlySanitizeOptions) |
37 | } | 38 | } |
38 | 39 | ||
39 | // --------------------------------------------------------------------------- | 40 | // --------------------------------------------------------------------------- |
@@ -47,30 +48,38 @@ export { | |||
47 | 48 | ||
48 | // Thanks: https://github.com/wavesheep/markdown-it-plain-text | 49 | // Thanks: https://github.com/wavesheep/markdown-it-plain-text |
49 | function plainTextPlugin (markdownIt: any) { | 50 | function plainTextPlugin (markdownIt: any) { |
50 | let lastSeparator = '' | ||
51 | |||
52 | function plainTextRule (state: any) { | 51 | function plainTextRule (state: any) { |
53 | const text = scan(state.tokens) | 52 | const text = scan(state.tokens) |
54 | 53 | ||
55 | markdownIt.plainText = text.replace(/\s+/g, ' ') | 54 | markdownIt.plainText = text |
56 | } | 55 | } |
57 | 56 | ||
58 | function scan (tokens: any[]) { | 57 | function scan (tokens: any[]) { |
58 | let lastSeparator = '' | ||
59 | let text = '' | 59 | let text = '' |
60 | 60 | ||
61 | for (const token of tokens) { | 61 | function buildSeparator (token: any) { |
62 | if (token.children !== null) { | ||
63 | text += scan(token.children) | ||
64 | continue | ||
65 | } | ||
66 | |||
67 | if (token.type === 'list_item_close') { | 62 | if (token.type === 'list_item_close') { |
68 | lastSeparator = ', ' | 63 | lastSeparator = ', ' |
69 | } else if (token.type.endsWith('_close')) { | 64 | } |
65 | |||
66 | if (token.tag === 'br' || token.type === 'paragraph_close') { | ||
70 | lastSeparator = ' ' | 67 | lastSeparator = ' ' |
71 | } else if (token.content) { | 68 | } |
72 | text += lastSeparator | 69 | } |
73 | text += token.content | 70 | |
71 | for (const token of tokens) { | ||
72 | buildSeparator(token) | ||
73 | |||
74 | if (token.type !== 'inline') continue | ||
75 | |||
76 | for (const child of token.children) { | ||
77 | buildSeparator(child) | ||
78 | |||
79 | if (!child.content) continue | ||
80 | |||
81 | text += lastSeparator + child.content | ||
82 | lastSeparator = '' | ||
74 | } | 83 | } |
75 | } | 84 | } |
76 | 85 | ||