diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-10-26 15:01:47 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-10-26 15:01:47 +0200 |
commit | 9d9597df427542eb5c7d3ba8ff5aeb146fab40e2 (patch) | |
tree | 5098facc5f2d70d4ad7871e6736e6f9d9d9a797a /client/src/app/videos | |
parent | 4077df72c634ff17aaf69cc612fc6bb8d68b1ed8 (diff) | |
download | PeerTube-9d9597df427542eb5c7d3ba8ff5aeb146fab40e2.tar.gz PeerTube-9d9597df427542eb5c7d3ba8ff5aeb146fab40e2.tar.zst PeerTube-9d9597df427542eb5c7d3ba8ff5aeb146fab40e2.zip |
Add markdown support to video description
Diffstat (limited to 'client/src/app/videos')
8 files changed, 67 insertions, 8 deletions
diff --git a/client/src/app/videos/+video-edit/video-update.component.ts b/client/src/app/videos/+video-edit/video-update.component.ts index 70cb334fd..30390ac05 100644 --- a/client/src/app/videos/+video-edit/video-update.component.ts +++ b/client/src/app/videos/+video-edit/video-update.component.ts | |||
@@ -87,7 +87,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
87 | this.videoService.getVideo(uuid) | 87 | this.videoService.getVideo(uuid) |
88 | .subscribe( | 88 | .subscribe( |
89 | video => { | 89 | video => { |
90 | this.video = video | 90 | this.video = new VideoEdit(video) |
91 | 91 | ||
92 | this.hydrateFormFromVideo() | 92 | this.hydrateFormFromVideo() |
93 | }, | 93 | }, |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 5d5827344..6e502aae2 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -128,9 +128,7 @@ | |||
128 | Published on {{ video.createdAt | date:'short' }} | 128 | Published on {{ video.createdAt | date:'short' }} |
129 | </div> | 129 | </div> |
130 | 130 | ||
131 | <div class="video-details-description"> | 131 | <div class="video-details-description" [innerHTML]="videoHTMLDescription"></div> |
132 | {{ video.description }} | ||
133 | </div> | ||
134 | </div> | 132 | </div> |
135 | 133 | ||
136 | <div class="video-details-attributes col-xs-4 col-md-3"> | 134 | <div class="video-details-attributes col-xs-4 col-md-3"> |
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 529e2e84f..2e1adb043 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -13,7 +13,7 @@ import { AuthService, ConfirmService } from '../../core' | |||
13 | import { VideoDownloadComponent } from './video-download.component' | 13 | import { VideoDownloadComponent } from './video-download.component' |
14 | import { VideoShareComponent } from './video-share.component' | 14 | import { VideoShareComponent } from './video-share.component' |
15 | import { VideoReportComponent } from './video-report.component' | 15 | import { VideoReportComponent } from './video-report.component' |
16 | import { VideoDetails, VideoService } from '../shared' | 16 | import { VideoDetails, VideoService, MarkdownService } from '../shared' |
17 | import { VideoBlacklistService } from '../../shared' | 17 | import { VideoBlacklistService } from '../../shared' |
18 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' | 18 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' |
19 | 19 | ||
@@ -38,6 +38,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
38 | video: VideoDetails = null | 38 | video: VideoDetails = null |
39 | videoPlayerLoaded = false | 39 | videoPlayerLoaded = false |
40 | videoNotFound = false | 40 | videoNotFound = false |
41 | videoHTMLDescription = '' | ||
41 | 42 | ||
42 | private paramsSub: Subscription | 43 | private paramsSub: Subscription |
43 | 44 | ||
@@ -50,7 +51,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
50 | private confirmService: ConfirmService, | 51 | private confirmService: ConfirmService, |
51 | private metaService: MetaService, | 52 | private metaService: MetaService, |
52 | private authService: AuthService, | 53 | private authService: AuthService, |
53 | private notificationsService: NotificationsService | 54 | private notificationsService: NotificationsService, |
55 | private markdownService: MarkdownService | ||
54 | ) {} | 56 | ) {} |
55 | 57 | ||
56 | ngOnInit () { | 58 | ngOnInit () { |
@@ -259,6 +261,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
259 | }) | 261 | }) |
260 | }) | 262 | }) |
261 | 263 | ||
264 | this.videoHTMLDescription = this.markdownService.markdownToHTML(this.video.description) | ||
265 | |||
262 | this.setOpenGraphTags() | 266 | this.setOpenGraphTags() |
263 | this.checkUserRating() | 267 | this.checkUserRating() |
264 | } | 268 | } |
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 c6c1344ce..1b983200d 100644 --- a/client/src/app/videos/+video-watch/video-watch.module.ts +++ b/client/src/app/videos/+video-watch/video-watch.module.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { NgModule } from '@angular/core' | 1 | import { NgModule } from '@angular/core' |
2 | 2 | ||
3 | import { VideoWatchRoutingModule } from './video-watch-routing.module' | 3 | import { VideoWatchRoutingModule } from './video-watch-routing.module' |
4 | import { VideoService } from '../shared' | 4 | import { VideoService, MarkdownService } from '../shared' |
5 | import { SharedModule } from '../../shared' | 5 | import { SharedModule } from '../../shared' |
6 | 6 | ||
7 | import { VideoWatchComponent } from './video-watch.component' | 7 | import { VideoWatchComponent } from './video-watch.component' |
@@ -28,6 +28,7 @@ import { VideoDownloadComponent } from './video-download.component' | |||
28 | ], | 28 | ], |
29 | 29 | ||
30 | providers: [ | 30 | providers: [ |
31 | MarkdownService, | ||
31 | VideoService | 32 | VideoService |
32 | ] | 33 | ] |
33 | }) | 34 | }) |
diff --git a/client/src/app/videos/shared/index.ts b/client/src/app/videos/shared/index.ts index dcaa4e090..09d961dd3 100644 --- a/client/src/app/videos/shared/index.ts +++ b/client/src/app/videos/shared/index.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | export * from './sort-field.type' | 1 | export * from './sort-field.type' |
2 | export * from './markdown.service' | ||
2 | export * from './video.model' | 3 | export * from './video.model' |
3 | export * from './video-details.model' | 4 | export * from './video-details.model' |
4 | export * from './video-edit.model' | 5 | export * from './video-edit.model' |
diff --git a/client/src/app/videos/shared/markdown.service.ts b/client/src/app/videos/shared/markdown.service.ts new file mode 100644 index 000000000..d8b5b76b6 --- /dev/null +++ b/client/src/app/videos/shared/markdown.service.ts | |||
@@ -0,0 +1,40 @@ | |||
1 | import { Injectable } from '@angular/core' | ||
2 | |||
3 | import * as MarkdownIt from 'markdown-it' | ||
4 | |||
5 | @Injectable() | ||
6 | export class MarkdownService { | ||
7 | private markdownIt: MarkdownIt.MarkdownIt | ||
8 | |||
9 | constructor () { | ||
10 | this.markdownIt = new MarkdownIt('zero', { linkify: true }) | ||
11 | .enable('linkify') | ||
12 | .enable('autolink') | ||
13 | .enable('emphasis') | ||
14 | .enable('link') | ||
15 | .enable('newline') | ||
16 | |||
17 | // Snippet from markdown-it documentation: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer | ||
18 | const defaultRender = this.markdownIt.renderer.rules.link_open || function (tokens, idx, options, env, self) { | ||
19 | return self.renderToken(tokens, idx, options) | ||
20 | } | ||
21 | |||
22 | this.markdownIt.renderer.rules.link_open = function (tokens, idx, options, env, self) { | ||
23 | // If you are sure other plugins can't add `target` - drop check below | ||
24 | const aIndex = tokens[idx].attrIndex('target') | ||
25 | |||
26 | if (aIndex < 0) { | ||
27 | tokens[idx].attrPush(['target', '_blank']) // add new attribute | ||
28 | } else { | ||
29 | tokens[idx].attrs[aIndex][1] = '_blank' // replace value of existing attr | ||
30 | } | ||
31 | |||
32 | // pass token to default renderer. | ||
33 | return defaultRender(tokens, idx, options, env, self) | ||
34 | } | ||
35 | } | ||
36 | |||
37 | markdownToHTML (markdown: string) { | ||
38 | return this.markdownIt.render(markdown) | ||
39 | } | ||
40 | } | ||
diff --git a/client/src/app/videos/shared/video-edit.model.ts b/client/src/app/videos/shared/video-edit.model.ts index f30d8feba..e0b7bf130 100644 --- a/client/src/app/videos/shared/video-edit.model.ts +++ b/client/src/app/videos/shared/video-edit.model.ts | |||
@@ -1,3 +1,5 @@ | |||
1 | import { VideoDetails } from './video-details.model' | ||
2 | |||
1 | export class VideoEdit { | 3 | export class VideoEdit { |
2 | category: number | 4 | category: number |
3 | licence: number | 5 | licence: number |
@@ -10,6 +12,19 @@ export class VideoEdit { | |||
10 | uuid?: string | 12 | uuid?: string |
11 | id?: number | 13 | id?: number |
12 | 14 | ||
15 | constructor (videoDetails: VideoDetails) { | ||
16 | this.id = videoDetails.id | ||
17 | this.uuid = videoDetails.uuid | ||
18 | this.category = videoDetails.category | ||
19 | this.licence = videoDetails.licence | ||
20 | this.language = videoDetails.language | ||
21 | this.description = videoDetails.description | ||
22 | this.name = videoDetails.name | ||
23 | this.tags = videoDetails.tags | ||
24 | this.nsfw = videoDetails.nsfw | ||
25 | this.channel = videoDetails.channel.id | ||
26 | } | ||
27 | |||
13 | patch (values: Object) { | 28 | patch (values: Object) { |
14 | Object.keys(values).forEach((key) => { | 29 | Object.keys(values).forEach((key) => { |
15 | this[key] = values[key] | 30 | this[key] = values[key] |
diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts index 06fb3313e..8fdc1f213 100644 --- a/client/src/app/videos/shared/video.service.ts +++ b/client/src/app/videos/shared/video.service.ts | |||
@@ -36,7 +36,7 @@ export class VideoService { | |||
36 | private restService: RestService | 36 | private restService: RestService |
37 | ) {} | 37 | ) {} |
38 | 38 | ||
39 | getVideo (uuid: string) { | 39 | getVideo (uuid: string): Observable<VideoDetails> { |
40 | return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid) | 40 | return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid) |
41 | .map(videoHash => new VideoDetails(videoHash)) | 41 | .map(videoHash => new VideoDetails(videoHash)) |
42 | .catch((res) => this.restExtractor.handleError(res)) | 42 | .catch((res) => this.restExtractor.handleError(res)) |