Add links support in comments

This commit is contained in:
Chocobozzz 2018-02-20 11:04:21 +01:00
parent 5de8a55abc
commit 3d9eaae318
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
4 changed files with 27 additions and 9 deletions

View File

@ -2,7 +2,7 @@ import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild }
import { FormBuilder, FormGroup } from '@angular/forms' import { FormBuilder, FormGroup } from '@angular/forms'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { Observable } from 'rxjs/Observable' import { Observable } from 'rxjs/Observable'
import { VideoCommentCreate, VideoCommentThreadTree } from '../../../../../../shared/models/videos/video-comment.model' import { VideoCommentCreate } from '../../../../../../shared/models/videos/video-comment.model'
import { FormReactive } from '../../../shared' import { FormReactive } from '../../../shared'
import { VIDEO_COMMENT_TEXT } from '../../../shared/forms/form-validators/video-comment' import { VIDEO_COMMENT_TEXT } from '../../../shared/forms/form-validators/video-comment'
import { User } from '../../../shared/users' import { User } from '../../../shared/users'

View File

@ -1,4 +1,5 @@
import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core' import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'
import { MarkdownService } from '@app/videos/shared'
import * as sanitizeHtml from 'sanitize-html' import * as sanitizeHtml from 'sanitize-html'
import { Account as AccountInterface } from '../../../../../../shared/models/actors' import { Account as AccountInterface } from '../../../../../../shared/models/actors'
import { UserRight } from '../../../../../../shared/models/users' import { UserRight } from '../../../../../../shared/models/users'
@ -29,7 +30,10 @@ export class VideoCommentComponent implements OnInit, OnChanges {
sanitizedCommentHTML = '' sanitizedCommentHTML = ''
newParentComments = [] newParentComments = []
constructor (private authService: AuthService) {} constructor (
private authService: AuthService,
private markdownService: MarkdownService
) {}
get user () { get user () {
return this.authService.getUser() return this.authService.getUser()
@ -90,9 +94,13 @@ export class VideoCommentComponent implements OnInit, OnChanges {
private init () { private init () {
this.sanitizedCommentHTML = sanitizeHtml(this.comment.text, { this.sanitizedCommentHTML = sanitizeHtml(this.comment.text, {
allowedTags: [ 'p', 'span', 'br' ] allowedTags: [ 'a', 'p', 'span', 'br' ],
allowedSchemes: [ 'http', 'https' ]
}) })
// Convert possible markdown to html
this.sanitizedCommentHTML = this.markdownService.linkify(this.comment.text)
this.newParentComments = this.parentComments.concat([ this.comment ]) this.newParentComments = this.parentComments.concat([ this.comment ])
} }
} }

View File

@ -1,12 +1,14 @@
import { HttpClient, HttpParams } from '@angular/common/http' import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { lineFeedToHtml } from '@app/shared/misc/utils'
import { MarkdownService } from '@app/videos/shared'
import 'rxjs/add/operator/catch' import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map' import 'rxjs/add/operator/map'
import { immutableAssign, lineFeedToHtml } from '@app/shared/misc/utils'
import { Observable } from 'rxjs/Observable' import { Observable } from 'rxjs/Observable'
import { ResultList } from '../../../../../../shared/models' import { ResultList } from '../../../../../../shared/models'
import { import {
VideoComment as VideoCommentServerModel, VideoCommentCreate, VideoComment as VideoCommentServerModel,
VideoCommentCreate,
VideoCommentThreadTree VideoCommentThreadTree
} from '../../../../../../shared/models/videos/video-comment.model' } from '../../../../../../shared/models/videos/video-comment.model'
import { environment } from '../../../../environments/environment' import { environment } from '../../../../environments/environment'

View File

@ -5,6 +5,7 @@ import * as MarkdownIt from 'markdown-it'
@Injectable() @Injectable()
export class MarkdownService { export class MarkdownService {
private markdownIt: MarkdownIt.MarkdownIt private markdownIt: MarkdownIt.MarkdownIt
private linkifier: MarkdownIt.MarkdownIt
constructor () { constructor () {
this.markdownIt = new MarkdownIt('zero', { linkify: true, breaks: true }) this.markdownIt = new MarkdownIt('zero', { linkify: true, breaks: true })
@ -14,8 +15,11 @@ export class MarkdownService {
.enable('link') .enable('link')
.enable('newline') .enable('newline')
.enable('list') .enable('list')
this.setTargetToLinks(this.markdownIt)
this.setTargetToLinks() this.linkifier = new MarkdownIt('zero', { linkify: true })
.enable('linkify')
this.setTargetToLinks(this.linkifier)
} }
markdownToHTML (markdown: string) { markdownToHTML (markdown: string) {
@ -25,13 +29,17 @@ export class MarkdownService {
return html.replace(/<a[^>]+>([^<]+)<\/a>\s*...(<\/p>)?$/mi, '$1...') return html.replace(/<a[^>]+>([^<]+)<\/a>\s*...(<\/p>)?$/mi, '$1...')
} }
private setTargetToLinks () { linkify (text: string) {
return this.linkifier.render(text)
}
private setTargetToLinks (markdownIt: MarkdownIt.MarkdownIt) {
// Snippet from markdown-it documentation: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer // Snippet from markdown-it documentation: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
const defaultRender = this.markdownIt.renderer.rules.link_open || function (tokens, idx, options, env, self) { const defaultRender = markdownIt.renderer.rules.link_open || function (tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options) return self.renderToken(tokens, idx, options)
} }
this.markdownIt.renderer.rules.link_open = function (tokens, idx, options, env, self) { markdownIt.renderer.rules.link_open = function (tokens, idx, options, env, self) {
// If you are sure other plugins can't add `target` - drop check below // If you are sure other plugins can't add `target` - drop check below
const aIndex = tokens[idx].attrIndex('target') const aIndex = tokens[idx].attrIndex('target')