ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

92 lines
2.5 KiB

  1. import MarkdownItClass from 'markdown-it'
  2. // FIXME: use direct import: import markdownItEmoji from 'markdown-it-emoji/lib/light.mjs' if it improves perf'
  3. // when https://github.com/privatenumber/tsx/issues/334 is fixed
  4. import { light as markdownItEmoji } from 'markdown-it-emoji'
  5. import sanitizeHtml from 'sanitize-html'
  6. import { getDefaultSanitizeOptions, getTextOnlySanitizeOptions, TEXT_WITH_HTML_RULES } from '@peertube/peertube-core-utils'
  7. const defaultSanitizeOptions = getDefaultSanitizeOptions()
  8. const textOnlySanitizeOptions = getTextOnlySanitizeOptions()
  9. const markdownItForSafeHtml = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
  10. .enable(TEXT_WITH_HTML_RULES)
  11. .use(markdownItEmoji)
  12. const markdownItForPlainText = new MarkdownItClass('default', { linkify: false, breaks: true, html: false })
  13. .use(markdownItEmoji)
  14. .use(plainTextPlugin)
  15. const toSafeHtml = (text: string) => {
  16. if (!text) return ''
  17. // Restore line feed
  18. const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n')
  19. // Convert possible markdown (emojis, emphasis and lists) to html
  20. const html = markdownItForSafeHtml.render(textWithLineFeed)
  21. // Convert to safe Html
  22. return sanitizeHtml(html, defaultSanitizeOptions)
  23. }
  24. const mdToOneLinePlainText = (text: string) => {
  25. if (!text) return ''
  26. markdownItForPlainText.render(text)
  27. // Convert to safe Html
  28. return sanitizeHtml(markdownItForPlainText.plainText, textOnlySanitizeOptions)
  29. }
  30. // ---------------------------------------------------------------------------
  31. export {
  32. toSafeHtml,
  33. mdToOneLinePlainText
  34. }
  35. // ---------------------------------------------------------------------------
  36. // Thanks: https://github.com/wavesheep/markdown-it-plain-text
  37. function plainTextPlugin (markdownIt: any) {
  38. function plainTextRule (state: any) {
  39. const text = scan(state.tokens)
  40. markdownIt.plainText = text
  41. }
  42. function scan (tokens: any[]) {
  43. let lastSeparator = ''
  44. let text = ''
  45. function buildSeparator (token: any) {
  46. if (token.type === 'list_item_close') {
  47. lastSeparator = ', '
  48. }
  49. if (token.tag === 'br' || token.type === 'paragraph_close') {
  50. lastSeparator = ' '
  51. }
  52. }
  53. for (const token of tokens) {
  54. buildSeparator(token)
  55. if (token.type !== 'inline') continue
  56. for (const child of token.children) {
  57. buildSeparator(child)
  58. if (!child.content) continue
  59. text += lastSeparator + child.content
  60. lastSeparator = ''
  61. }
  62. }
  63. return text
  64. }
  65. markdownIt.core.ruler.push('plainText', plainTextRule)
  66. }