From 1506307f2f903ce0f80155072a33345c702b7c76 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 14 Jan 2019 16:48:38 +0100 Subject: Increase abuse length to 3000 And correctly handle new lines --- .../+video-watch/comment/linkifier.service.ts | 115 --------------------- .../comment/video-comment.component.ts | 27 +---- .../+video-watch/comment/video-comment.service.ts | 6 +- .../+video-watch/modal/video-support.component.ts | 3 +- .../videos/+video-watch/video-watch.component.ts | 2 +- .../app/videos/+video-watch/video-watch.module.ts | 4 - client/src/app/videos/shared/index.ts | 1 - client/src/app/videos/shared/markdown.service.ts | 79 -------------- 8 files changed, 8 insertions(+), 229 deletions(-) delete mode 100644 client/src/app/videos/+video-watch/comment/linkifier.service.ts delete mode 100644 client/src/app/videos/shared/index.ts delete mode 100644 client/src/app/videos/shared/markdown.service.ts (limited to 'client/src/app/videos') diff --git a/client/src/app/videos/+video-watch/comment/linkifier.service.ts b/client/src/app/videos/+video-watch/comment/linkifier.service.ts deleted file mode 100644 index 2529c9eaf..000000000 --- a/client/src/app/videos/+video-watch/comment/linkifier.service.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { Injectable } from '@angular/core' -import { getAbsoluteAPIUrl } from '@app/shared/misc/utils' -// FIXME: use @types/linkify when https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29682/files is merged? -const linkify = require('linkifyjs') -const linkifyHtml = require('linkifyjs/html') - -@Injectable() -export class LinkifierService { - - static CLASSNAME = 'linkified' - - private linkifyOptions = { - className: { - mention: LinkifierService.CLASSNAME + '-mention', - url: LinkifierService.CLASSNAME + '-url' - } - } - - constructor () { - // Apply plugin - this.mentionWithDomainPlugin(linkify) - } - - linkify (text: string) { - return linkifyHtml(text, this.linkifyOptions) - } - - private mentionWithDomainPlugin (linkify: any) { - const TT = linkify.scanner.TOKENS // Text tokens - const { TOKENS: MT, State } = linkify.parser // Multi tokens, state - const MultiToken = MT.Base - const S_START = linkify.parser.start - - const TT_AT = TT.AT - const TT_DOMAIN = TT.DOMAIN - const TT_LOCALHOST = TT.LOCALHOST - const TT_NUM = TT.NUM - const TT_COLON = TT.COLON - const TT_SLASH = TT.SLASH - const TT_TLD = TT.TLD - const TT_UNDERSCORE = TT.UNDERSCORE - const TT_DOT = TT.DOT - - function MENTION (this: any, value: any) { - this.v = value - } - - linkify.inherits(MultiToken, MENTION, { - type: 'mentionWithDomain', - isLink: true, - toHref () { - return getAbsoluteAPIUrl() + '/services/redirect/accounts/' + this.toString().substr(1) - } - }) - - const S_AT = S_START.jump(TT_AT) // @ - const S_AT_SYMS = new State() - const S_MENTION = new State(MENTION) - const S_MENTION_DIVIDER = new State() - const S_MENTION_DIVIDER_SYMS = new State() - - // @_, - S_AT.on(TT_UNDERSCORE, S_AT_SYMS) - - // @_* - S_AT_SYMS - .on(TT_UNDERSCORE, S_AT_SYMS) - .on(TT_DOT, S_AT_SYMS) - - // Valid mention (not made up entirely of symbols) - S_AT - .on(TT_DOMAIN, S_MENTION) - .on(TT_LOCALHOST, S_MENTION) - .on(TT_TLD, S_MENTION) - .on(TT_NUM, S_MENTION) - - S_AT_SYMS - .on(TT_DOMAIN, S_MENTION) - .on(TT_LOCALHOST, S_MENTION) - .on(TT_TLD, S_MENTION) - .on(TT_NUM, S_MENTION) - - // More valid mentions - S_MENTION - .on(TT_DOMAIN, S_MENTION) - .on(TT_LOCALHOST, S_MENTION) - .on(TT_TLD, S_MENTION) - .on(TT_COLON, S_MENTION) - .on(TT_NUM, S_MENTION) - .on(TT_UNDERSCORE, S_MENTION) - - // Mention with a divider - S_MENTION - .on(TT_AT, S_MENTION_DIVIDER) - .on(TT_SLASH, S_MENTION_DIVIDER) - .on(TT_DOT, S_MENTION_DIVIDER) - - // Mention _ trailing stash plus syms - S_MENTION_DIVIDER.on(TT_UNDERSCORE, S_MENTION_DIVIDER_SYMS) - S_MENTION_DIVIDER_SYMS.on(TT_UNDERSCORE, S_MENTION_DIVIDER_SYMS) - - // Once we get a word token, mentions can start up again - S_MENTION_DIVIDER - .on(TT_DOMAIN, S_MENTION) - .on(TT_LOCALHOST, S_MENTION) - .on(TT_TLD, S_MENTION) - .on(TT_NUM, S_MENTION) - - S_MENTION_DIVIDER_SYMS - .on(TT_DOMAIN, S_MENTION) - .on(TT_LOCALHOST, S_MENTION) - .on(TT_TLD, S_MENTION) - .on(TT_NUM, S_MENTION) - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.ts b/client/src/app/videos/+video-watch/comment/video-comment.component.ts index 00f0460a1..aba7f9d1c 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment.component.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment.component.ts @@ -1,11 +1,10 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core' -import { LinkifierService } from '@app/videos/+video-watch/comment/linkifier.service' -import * as sanitizeHtml from 'sanitize-html' import { UserRight } from '../../../../../../shared/models/users' import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/video-comment.model' import { AuthService } from '../../../core/auth' import { Video } from '../../../shared/video/video.model' import { VideoComment } from './video-comment.model' +import { HtmlRendererService } from '@app/shared/renderer' @Component({ selector: 'my-video-comment', @@ -29,7 +28,7 @@ export class VideoCommentComponent implements OnInit, OnChanges { newParentComments: VideoComment[] = [] constructor ( - private linkifierService: LinkifierService, + private htmlRenderer: HtmlRendererService, private authService: AuthService ) {} @@ -87,27 +86,7 @@ export class VideoCommentComponent implements OnInit, OnChanges { } private init () { - // Convert possible markdown to html - const html = this.linkifierService.linkify(this.comment.text) - - this.sanitizedCommentHTML = sanitizeHtml(html, { - allowedTags: [ 'a', 'p', 'span', 'br' ], - allowedSchemes: [ 'http', 'https' ], - allowedAttributes: { - 'a': [ 'href', 'class', 'target' ] - }, - transformTags: { - a: (tagName, attribs) => { - return { - tagName, - attribs: Object.assign(attribs, { - target: '_blank', - rel: 'noopener noreferrer' - }) - } - } - } - }) + this.sanitizedCommentHTML = this.htmlRenderer.toSafeHtml(this.comment.text) this.newParentComments = this.parentComments.concat([ this.comment ]) } diff --git a/client/src/app/videos/+video-watch/comment/video-comment.service.ts b/client/src/app/videos/+video-watch/comment/video-comment.service.ts index 921447d5b..b8e5878c5 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment.service.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment.service.ts @@ -1,7 +1,7 @@ import { catchError, map } from 'rxjs/operators' import { HttpClient, HttpParams } from '@angular/common/http' import { Injectable } from '@angular/core' -import { lineFeedToHtml } from '@app/shared/misc/utils' +import { objectLineFeedToHtml } from '@app/shared/misc/utils' import { Observable } from 'rxjs' import { ResultList, FeedFormat } from '../../../../../../shared/models' import { @@ -28,7 +28,7 @@ export class VideoCommentService { addCommentThread (videoId: number | string, comment: VideoCommentCreate) { const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads' - const normalizedComment = lineFeedToHtml(comment, 'text') + const normalizedComment = objectLineFeedToHtml(comment, 'text') return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment) .pipe( @@ -39,7 +39,7 @@ export class VideoCommentService { addCommentReply (videoId: number | string, inReplyToCommentId: number, comment: VideoCommentCreate) { const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comments/' + inReplyToCommentId - const normalizedComment = lineFeedToHtml(comment, 'text') + const normalizedComment = objectLineFeedToHtml(comment, 'text') return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment) .pipe( diff --git a/client/src/app/videos/+video-watch/modal/video-support.component.ts b/client/src/app/videos/+video-watch/modal/video-support.component.ts index 154002120..deb8fbc67 100644 --- a/client/src/app/videos/+video-watch/modal/video-support.component.ts +++ b/client/src/app/videos/+video-watch/modal/video-support.component.ts @@ -1,8 +1,7 @@ import { Component, Input, ViewChild } from '@angular/core' -import { MarkdownService } from '@app/videos/shared' - import { VideoDetails } from '../../../shared/video/video-details.model' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { MarkdownService } from '@app/shared/renderer' @Component({ selector: 'my-video-support', diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 67c5254b3..ee504bc58 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -19,7 +19,6 @@ import { AuthService, ConfirmService } from '../../core' import { RestExtractor, VideoBlacklistService } from '../../shared' import { VideoDetails } from '../../shared/video/video-details.model' import { VideoService } from '../../shared/video/video.service' -import { MarkdownService } from '../shared' import { VideoDownloadComponent } from './modal/video-download.component' import { VideoReportComponent } from './modal/video-report.component' import { VideoShareComponent } from './modal/video-share.component' @@ -30,6 +29,7 @@ import { I18n } from '@ngx-translate/i18n-polyfill' import { environment } from '../../../environments/environment' import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' import { VideoCaptionService } from '@app/shared/video-caption' +import { MarkdownService } from '@app/shared/renderer' @Component({ selector: 'my-video-watch', diff --git a/client/src/app/videos/+video-watch/video-watch.module.ts b/client/src/app/videos/+video-watch/video-watch.module.ts index 54a12c126..2f448db78 100644 --- a/client/src/app/videos/+video-watch/video-watch.module.ts +++ b/client/src/app/videos/+video-watch/video-watch.module.ts @@ -1,9 +1,7 @@ import { NgModule } from '@angular/core' -import { LinkifierService } from '@app/videos/+video-watch/comment/linkifier.service' import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component' import { ClipboardModule } from 'ngx-clipboard' import { SharedModule } from '../../shared' -import { MarkdownService } from '../shared' import { VideoCommentAddComponent } from './comment/video-comment-add.component' import { VideoCommentComponent } from './comment/video-comment.component' import { VideoCommentService } from './comment/video-comment.service' @@ -46,8 +44,6 @@ import { RecommendationsModule } from '@app/videos/recommendations/recommendatio ], providers: [ - MarkdownService, - LinkifierService, VideoCommentService ] }) diff --git a/client/src/app/videos/shared/index.ts b/client/src/app/videos/shared/index.ts deleted file mode 100644 index 7a66944b9..000000000 --- a/client/src/app/videos/shared/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './markdown.service' diff --git a/client/src/app/videos/shared/markdown.service.ts b/client/src/app/videos/shared/markdown.service.ts deleted file mode 100644 index 07017eca5..000000000 --- a/client/src/app/videos/shared/markdown.service.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Injectable } from '@angular/core' - -import * as MarkdownIt from 'markdown-it' - -@Injectable() -export class MarkdownService { - static TEXT_RULES = [ - 'linkify', - 'autolink', - 'emphasis', - 'link', - 'newline', - 'list' - ] - static ENHANCED_RULES = MarkdownService.TEXT_RULES.concat([ 'image' ]) - - private textMarkdownIt: MarkdownIt.MarkdownIt - private enhancedMarkdownIt: MarkdownIt.MarkdownIt - - constructor () { - this.textMarkdownIt = this.createMarkdownIt(MarkdownService.TEXT_RULES) - this.enhancedMarkdownIt = this.createMarkdownIt(MarkdownService.ENHANCED_RULES) - } - - textMarkdownToHTML (markdown: string) { - if (!markdown) return '' - - const html = this.textMarkdownIt.render(markdown) - return this.avoidTruncatedTags(html) - } - - enhancedMarkdownToHTML (markdown: string) { - if (!markdown) return '' - - const html = this.enhancedMarkdownIt.render(markdown) - return this.avoidTruncatedTags(html) - } - - private createMarkdownIt (rules: string[]) { - const markdownIt = new MarkdownIt('zero', { linkify: true, breaks: true }) - - for (let rule of rules) { - markdownIt.enable(rule) - } - - this.setTargetToLinks(markdownIt) - - return markdownIt - } - - private setTargetToLinks (markdownIt: MarkdownIt.MarkdownIt) { - // Snippet from markdown-it documentation: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer - const defaultRender = markdownIt.renderer.rules.link_open || function (tokens, idx, options, env, self) { - return self.renderToken(tokens, idx, options) - } - - markdownIt.renderer.rules.link_open = function (tokens, index, options, env, self) { - const token = tokens[index] - - const targetIndex = token.attrIndex('target') - if (targetIndex < 0) token.attrPush([ 'target', '_blank' ]) - else token.attrs[targetIndex][1] = '_blank' - - const relIndex = token.attrIndex('rel') - if (relIndex < 0) token.attrPush([ 'rel', 'noopener noreferrer' ]) - else token.attrs[relIndex][1] = 'noopener noreferrer' - - // pass token to default renderer. - return defaultRender(tokens, index, options, env, self) - } - } - - private avoidTruncatedTags (html: string) { - return html.replace(/\*\*?([^*]+)$/, '$1') - .replace(/]+>([^<]+)<\/a>\s*...((<\/p>)|(<\/li>)|(<\/strong>))?$/mi, '$1...') - .replace(/\[[^\]]+\]?\(?([^\)]+)$/, '$1') - - } -} -- cgit v1.2.3