aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/helpers/markdown.ts15
-rw-r--r--server/lib/client-html.ts22
-rw-r--r--server/tests/client.ts9
3 files changed, 28 insertions, 18 deletions
diff --git a/server/helpers/markdown.ts b/server/helpers/markdown.ts
index c8fb31c8c..7c4a1a8b1 100644
--- a/server/helpers/markdown.ts
+++ b/server/helpers/markdown.ts
@@ -19,8 +19,21 @@ const toSafeHtml = text => {
19 return sanitizeHtml(html, SANITIZE_OPTIONS) 19 return sanitizeHtml(html, SANITIZE_OPTIONS)
20} 20}
21 21
22const mdToPlainText = text => {
23 // Convert possible markdown (emojis, emphasis and lists) to html
24 const html = markdownIt.render(text)
25
26 // Convert to safe Html
27 const safeHtml = sanitizeHtml(html, SANITIZE_OPTIONS)
28
29 return safeHtml.replace(/<[^>]+>/g, '')
30 .replace(/\n$/, '')
31 .replace('\n', ', ')
32}
33
22// --------------------------------------------------------------------------- 34// ---------------------------------------------------------------------------
23 35
24export { 36export {
25 toSafeHtml 37 toSafeHtml,
38 mdToPlainText
26} 39}
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index 5485376d3..203bd3893 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -24,7 +24,7 @@ import { VideoChannelModel } from '../models/video/video-channel'
24import { getActivityStreamDuration } from '../models/video/video-format-utils' 24import { getActivityStreamDuration } from '../models/video/video-format-utils'
25import { VideoPlaylistModel } from '../models/video/video-playlist' 25import { VideoPlaylistModel } from '../models/video/video-playlist'
26import { MAccountActor, MChannelActor } from '../types/models' 26import { MAccountActor, MChannelActor } from '../types/models'
27import { toSafeHtml } from '../helpers/markdown' 27import { mdToPlainText } from '../helpers/markdown'
28 28
29type Tags = { 29type Tags = {
30 ogType: string 30 ogType: string
@@ -55,10 +55,6 @@ type Tags = {
55 } 55 }
56} 56}
57 57
58const toPlainText = (content: string) => {
59 return toSafeHtml(content).replace(/<[^>]+>/g, '')
60}
61
62class ClientHtml { 58class ClientHtml {
63 59
64 private static htmlCache: { [path: string]: string } = {} 60 private static htmlCache: { [path: string]: string } = {}
@@ -99,13 +95,13 @@ class ClientHtml {
99 } 95 }
100 96
101 let customHtml = ClientHtml.addTitleTag(html, escapeHTML(video.name)) 97 let customHtml = ClientHtml.addTitleTag(html, escapeHTML(video.name))
102 customHtml = ClientHtml.addDescriptionTag(customHtml, toPlainText(video.description)) 98 customHtml = ClientHtml.addDescriptionTag(customHtml, mdToPlainText(video.description))
103 99
104 const url = WEBSERVER.URL + video.getWatchStaticPath() 100 const url = WEBSERVER.URL + video.getWatchStaticPath()
105 const originUrl = video.url 101 const originUrl = video.url
106 const title = escapeHTML(video.name) 102 const title = escapeHTML(video.name)
107 const siteName = escapeHTML(CONFIG.INSTANCE.NAME) 103 const siteName = escapeHTML(CONFIG.INSTANCE.NAME)
108 const description = toPlainText(video.description) 104 const description = mdToPlainText(video.description)
109 105
110 const image = { 106 const image = {
111 url: WEBSERVER.URL + video.getPreviewStaticPath() 107 url: WEBSERVER.URL + video.getPreviewStaticPath()
@@ -157,13 +153,13 @@ class ClientHtml {
157 } 153 }
158 154
159 let customHtml = ClientHtml.addTitleTag(html, escapeHTML(videoPlaylist.name)) 155 let customHtml = ClientHtml.addTitleTag(html, escapeHTML(videoPlaylist.name))
160 customHtml = ClientHtml.addDescriptionTag(customHtml, toPlainText(videoPlaylist.description)) 156 customHtml = ClientHtml.addDescriptionTag(customHtml, mdToPlainText(videoPlaylist.description))
161 157
162 const url = videoPlaylist.getWatchUrl() 158 const url = videoPlaylist.getWatchUrl()
163 const originUrl = videoPlaylist.url 159 const originUrl = videoPlaylist.url
164 const title = escapeHTML(videoPlaylist.name) 160 const title = escapeHTML(videoPlaylist.name)
165 const siteName = escapeHTML(CONFIG.INSTANCE.NAME) 161 const siteName = escapeHTML(CONFIG.INSTANCE.NAME)
166 const description = toPlainText(videoPlaylist.description) 162 const description = mdToPlainText(videoPlaylist.description)
167 163
168 const image = { 164 const image = {
169 url: videoPlaylist.getThumbnailUrl() 165 url: videoPlaylist.getThumbnailUrl()
@@ -241,13 +237,13 @@ class ClientHtml {
241 } 237 }
242 238
243 let customHtml = ClientHtml.addTitleTag(html, escapeHTML(entity.getDisplayName())) 239 let customHtml = ClientHtml.addTitleTag(html, escapeHTML(entity.getDisplayName()))
244 customHtml = ClientHtml.addDescriptionTag(customHtml, toPlainText(entity.description)) 240 customHtml = ClientHtml.addDescriptionTag(customHtml, mdToPlainText(entity.description))
245 241
246 const url = entity.getLocalUrl() 242 const url = entity.getLocalUrl()
247 const originUrl = entity.Actor.url 243 const originUrl = entity.Actor.url
248 const siteName = escapeHTML(CONFIG.INSTANCE.NAME) 244 const siteName = escapeHTML(CONFIG.INSTANCE.NAME)
249 const title = escapeHTML(entity.getDisplayName()) 245 const title = escapeHTML(entity.getDisplayName())
250 const description = toPlainText(entity.description) 246 const description = mdToPlainText(entity.description)
251 247
252 const image = { 248 const image = {
253 url: entity.Actor.getAvatarUrl(), 249 url: entity.Actor.getAvatarUrl(),
@@ -383,7 +379,7 @@ class ClientHtml {
383 } 379 }
384 380
385 metaTags['og:url'] = tags.url 381 metaTags['og:url'] = tags.url
386 metaTags['og:description'] = tags.description 382 metaTags['og:description'] = mdToPlainText(tags.description)
387 383
388 if (tags.embed) { 384 if (tags.embed) {
389 metaTags['og:video:url'] = tags.embed.url 385 metaTags['og:video:url'] = tags.embed.url
@@ -399,7 +395,7 @@ class ClientHtml {
399 private static generateStandardMetaTags (tags: Tags) { 395 private static generateStandardMetaTags (tags: Tags) {
400 return { 396 return {
401 name: tags.title, 397 name: tags.title,
402 description: tags.description, 398 description: mdToPlainText(tags.description),
403 image: tags.image.url 399 image: tags.image.url
404 } 400 }
405 } 401 }
diff --git a/server/tests/client.ts b/server/tests/client.ts
index d608764ee..3c99bcd1f 100644
--- a/server/tests/client.ts
+++ b/server/tests/client.ts
@@ -39,7 +39,8 @@ describe('Test a client controllers', function () {
39 let account: Account 39 let account: Account
40 40
41 const videoName = 'my super name for server 1' 41 const videoName = 'my super name for server 1'
42 const videoDescription = 'my super description for server 1' 42 const videoDescription = 'my<br> super __description__ for *server* 1<p></p>'
43 const videoDescriptionPlainText = 'my super description for server 1'
43 44
44 const playlistName = 'super playlist name' 45 const playlistName = 'super playlist name'
45 const playlistDescription = 'super playlist description' 46 const playlistDescription = 'super playlist description'
@@ -169,7 +170,7 @@ describe('Test a client controllers', function () {
169 .expect(HttpStatusCode.OK_200) 170 .expect(HttpStatusCode.OK_200)
170 171
171 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) 172 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`)
172 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`) 173 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`)
173 expect(res.text).to.contain('<meta property="og:type" content="video" />') 174 expect(res.text).to.contain('<meta property="og:type" content="video" />')
174 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`) 175 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`)
175 }) 176 })
@@ -181,7 +182,7 @@ describe('Test a client controllers', function () {
181 .expect(HttpStatusCode.OK_200) 182 .expect(HttpStatusCode.OK_200)
182 183
183 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) 184 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`)
184 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`) 185 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`)
185 expect(res.text).to.contain('<meta property="og:type" content="video" />') 186 expect(res.text).to.contain('<meta property="og:type" content="video" />')
186 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`) 187 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`)
187 }) 188 })
@@ -210,7 +211,7 @@ describe('Test a client controllers', function () {
210 expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />') 211 expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />')
211 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />') 212 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
212 expect(res.text).to.contain(`<meta property="twitter:title" content="${videoName}" />`) 213 expect(res.text).to.contain(`<meta property="twitter:title" content="${videoName}" />`)
213 expect(res.text).to.contain(`<meta property="twitter:description" content="${videoDescription}" />`) 214 expect(res.text).to.contain(`<meta property="twitter:description" content="${videoDescriptionPlainText}" />`)
214 }) 215 })
215 216
216 it('Should have valid twitter card on the watch playlist page', async function () { 217 it('Should have valid twitter card on the watch playlist page', async function () {