mirror of https://github.com/Chocobozzz/PeerTube
Refactor markdown/sanitize html code
parent
9afb5c10e5
commit
9ff36c2d70
|
@ -1,5 +1,6 @@
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { LinkifierService } from './linkifier.service'
|
import { LinkifierService } from './linkifier.service'
|
||||||
|
import { SANITIZE_OPTIONS } from '@shared/core-utils/renderer/html'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HtmlRendererService {
|
export class HtmlRendererService {
|
||||||
|
@ -25,27 +26,7 @@ export class HtmlRendererService {
|
||||||
// Convert possible markdown to html
|
// Convert possible markdown to html
|
||||||
const html = this.linkifier.linkify(text)
|
const html = this.linkifier.linkify(text)
|
||||||
|
|
||||||
return this.sanitizeHtml(html, {
|
return this.sanitizeHtml(html, SANITIZE_OPTIONS)
|
||||||
allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
|
|
||||||
allowedSchemes: [ 'http', 'https' ],
|
|
||||||
allowedAttributes: {
|
|
||||||
'a': [ 'href', 'class', 'target', 'rel' ]
|
|
||||||
},
|
|
||||||
transformTags: {
|
|
||||||
a: (tagName, attribs) => {
|
|
||||||
let rel = 'noopener noreferrer'
|
|
||||||
if (attribs.rel === 'me') rel += ' me'
|
|
||||||
|
|
||||||
return {
|
|
||||||
tagName,
|
|
||||||
attribs: Object.assign(attribs, {
|
|
||||||
target: '_blank',
|
|
||||||
rel
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadSanitizeHtml () {
|
private async loadSanitizeHtml () {
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import * as MarkdownIt from 'markdown-it'
|
import * as MarkdownIt from 'markdown-it'
|
||||||
import { buildVideoLink } from 'src/assets/player/utils'
|
import { buildVideoLink } from 'src/assets/player/utils'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
|
import {
|
||||||
|
COMPLETE_RULES,
|
||||||
|
ENHANCED_RULES,
|
||||||
|
ENHANCED_WITH_HTML_RULES,
|
||||||
|
TEXT_RULES,
|
||||||
|
TEXT_WITH_HTML_RULES
|
||||||
|
} from '@shared/core-utils/renderer/markdown'
|
||||||
import { HtmlRendererService } from './html-renderer.service'
|
import { HtmlRendererService } from './html-renderer.service'
|
||||||
|
|
||||||
type MarkdownParsers = {
|
type MarkdownParsers = {
|
||||||
|
@ -25,21 +32,6 @@ type MarkdownParserConfigs = {
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MarkdownService {
|
export class MarkdownService {
|
||||||
static TEXT_RULES = [
|
|
||||||
'linkify',
|
|
||||||
'autolink',
|
|
||||||
'emphasis',
|
|
||||||
'link',
|
|
||||||
'newline',
|
|
||||||
'list'
|
|
||||||
]
|
|
||||||
static TEXT_WITH_HTML_RULES = MarkdownService.TEXT_RULES.concat([ 'html_inline', 'html_block' ])
|
|
||||||
|
|
||||||
static ENHANCED_RULES = MarkdownService.TEXT_RULES.concat([ 'image' ])
|
|
||||||
static ENHANCED_WITH_HTML_RULES = MarkdownService.TEXT_WITH_HTML_RULES.concat([ 'image' ])
|
|
||||||
|
|
||||||
static COMPLETE_RULES = MarkdownService.ENHANCED_WITH_HTML_RULES.concat([ 'block', 'inline', 'heading', 'paragraph' ])
|
|
||||||
|
|
||||||
private markdownParsers: MarkdownParsers = {
|
private markdownParsers: MarkdownParsers = {
|
||||||
textMarkdownIt: null,
|
textMarkdownIt: null,
|
||||||
textWithHTMLMarkdownIt: null,
|
textWithHTMLMarkdownIt: null,
|
||||||
|
@ -48,13 +40,13 @@ export class MarkdownService {
|
||||||
completeMarkdownIt: null
|
completeMarkdownIt: null
|
||||||
}
|
}
|
||||||
private parsersConfig: MarkdownParserConfigs = {
|
private parsersConfig: MarkdownParserConfigs = {
|
||||||
textMarkdownIt: { rules: MarkdownService.TEXT_RULES, html: false },
|
textMarkdownIt: { rules: TEXT_RULES, html: false },
|
||||||
textWithHTMLMarkdownIt: { rules: MarkdownService.TEXT_WITH_HTML_RULES, html: true, escape: true },
|
textWithHTMLMarkdownIt: { rules: TEXT_WITH_HTML_RULES, html: true, escape: true },
|
||||||
|
|
||||||
enhancedMarkdownIt: { rules: MarkdownService.ENHANCED_RULES, html: false },
|
enhancedMarkdownIt: { rules: ENHANCED_RULES, html: false },
|
||||||
enhancedWithHTMLMarkdownIt: { rules: MarkdownService.ENHANCED_WITH_HTML_RULES, html: true, escape: true },
|
enhancedWithHTMLMarkdownIt: { rules: ENHANCED_WITH_HTML_RULES, html: true, escape: true },
|
||||||
|
|
||||||
completeMarkdownIt: { rules: MarkdownService.COMPLETE_RULES, html: true }
|
completeMarkdownIt: { rules: COMPLETE_RULES, html: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (private htmlRenderer: HtmlRendererService) {}
|
constructor (private htmlRenderer: HtmlRendererService) {}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { join } from 'path'
|
||||||
import { VideoChannelModel } from '@server/models/video/video-channel'
|
import { VideoChannelModel } from '@server/models/video/video-channel'
|
||||||
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
||||||
import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import'
|
import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import'
|
||||||
|
import { SANITIZE_OPTIONS, TEXT_WITH_HTML_RULES } from '@shared/core-utils'
|
||||||
import { AbuseState, EmailPayload, UserAbuse } from '@shared/models'
|
import { AbuseState, EmailPayload, UserAbuse } from '@shared/models'
|
||||||
import { SendEmailOptions } from '../../shared/models/server/emailer.model'
|
import { SendEmailOptions } from '../../shared/models/server/emailer.model'
|
||||||
import { isTestInstance, root } from '../helpers/core-utils'
|
import { isTestInstance, root } from '../helpers/core-utils'
|
||||||
|
@ -20,14 +21,7 @@ const markdownItEmoji = require('markdown-it-emoji/light')
|
||||||
const MarkdownItClass = require('markdown-it')
|
const MarkdownItClass = require('markdown-it')
|
||||||
const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
|
const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
|
||||||
|
|
||||||
markdownIt.enable([
|
markdownIt.enable(TEXT_WITH_HTML_RULES)
|
||||||
'linkify',
|
|
||||||
'autolink',
|
|
||||||
'emphasis',
|
|
||||||
'link',
|
|
||||||
'newline',
|
|
||||||
'list'
|
|
||||||
])
|
|
||||||
|
|
||||||
markdownIt.use(markdownItEmoji)
|
markdownIt.use(markdownItEmoji)
|
||||||
|
|
||||||
|
@ -39,27 +33,7 @@ const toSafeHtml = text => {
|
||||||
const html = markdownIt.render(textWithLineFeed)
|
const html = markdownIt.render(textWithLineFeed)
|
||||||
|
|
||||||
// Convert to safe Html
|
// Convert to safe Html
|
||||||
return sanitizeHtml(html, {
|
return sanitizeHtml(html, SANITIZE_OPTIONS)
|
||||||
allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
|
|
||||||
allowedSchemes: [ 'http', 'https' ],
|
|
||||||
allowedAttributes: {
|
|
||||||
a: [ 'href', 'class', 'target', 'rel' ]
|
|
||||||
},
|
|
||||||
transformTags: {
|
|
||||||
a: (tagName, attribs) => {
|
|
||||||
let rel = 'noopener noreferrer'
|
|
||||||
if (attribs.rel === 'me') rel += ' me'
|
|
||||||
|
|
||||||
return {
|
|
||||||
tagName,
|
|
||||||
attribs: Object.assign(attribs, {
|
|
||||||
target: '_blank',
|
|
||||||
rel
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Email = require('email-templates')
|
const Email = require('email-templates')
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
export * from './abuse'
|
||||||
|
export * from './i18n'
|
||||||
export * from './logs'
|
export * from './logs'
|
||||||
export * from './miscs'
|
export * from './miscs'
|
||||||
export * from './plugins'
|
export * from './plugins'
|
||||||
|
export * from './renderer'
|
||||||
|
export * from './users'
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
export const SANITIZE_OPTIONS = {
|
||||||
|
allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
|
||||||
|
allowedSchemes: [ 'http', 'https' ],
|
||||||
|
allowedAttributes: {
|
||||||
|
a: [ 'href', 'class', 'target', 'rel' ]
|
||||||
|
},
|
||||||
|
transformTags: {
|
||||||
|
a: (tagName, attribs) => {
|
||||||
|
let rel = 'noopener noreferrer'
|
||||||
|
if (attribs.rel === 'me') rel += ' me'
|
||||||
|
|
||||||
|
return {
|
||||||
|
tagName,
|
||||||
|
attribs: Object.assign(attribs, {
|
||||||
|
target: '_blank',
|
||||||
|
rel
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './markdown'
|
||||||
|
export * from './html'
|
|
@ -0,0 +1,23 @@
|
||||||
|
export const TEXT_RULES = [
|
||||||
|
'linkify',
|
||||||
|
'autolink',
|
||||||
|
'emphasis',
|
||||||
|
'link',
|
||||||
|
'newline',
|
||||||
|
'list'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const TEXT_WITH_HTML_RULES = TEXT_RULES.concat([
|
||||||
|
'html_inline',
|
||||||
|
'html_block'
|
||||||
|
])
|
||||||
|
|
||||||
|
export const ENHANCED_RULES = TEXT_RULES.concat([ 'image' ])
|
||||||
|
export const ENHANCED_WITH_HTML_RULES = TEXT_WITH_HTML_RULES.concat([ 'image' ])
|
||||||
|
|
||||||
|
export const COMPLETE_RULES = ENHANCED_WITH_HTML_RULES.concat([
|
||||||
|
'block',
|
||||||
|
'inline',
|
||||||
|
'heading',
|
||||||
|
'paragraph'
|
||||||
|
])
|
Loading…
Reference in New Issue