diff options
Diffstat (limited to 'client/src/app/shared/shared-custom-markup/custom-markup.service.ts')
-rw-r--r-- | client/src/app/shared/shared-custom-markup/custom-markup.service.ts | 65 |
1 files changed, 56 insertions, 9 deletions
diff --git a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts index dbb07914e..a3b7303d8 100644 --- a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts +++ b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts | |||
@@ -3,6 +3,7 @@ import { MarkdownService } from '@app/core' | |||
3 | import { | 3 | import { |
4 | ButtonMarkupData, | 4 | ButtonMarkupData, |
5 | ChannelMiniatureMarkupData, | 5 | ChannelMiniatureMarkupData, |
6 | ContainerMarkupData, | ||
6 | EmbedMarkupData, | 7 | EmbedMarkupData, |
7 | PlaylistMiniatureMarkupData, | 8 | PlaylistMiniatureMarkupData, |
8 | VideoMiniatureMarkupData, | 9 | VideoMiniatureMarkupData, |
@@ -18,11 +19,12 @@ import { | |||
18 | VideosListMarkupComponent | 19 | VideosListMarkupComponent |
19 | } from './peertube-custom-tags' | 20 | } from './peertube-custom-tags' |
20 | 21 | ||
21 | type BuilderFunction = (el: HTMLElement) => ComponentRef<any> | 22 | type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<any> |
23 | type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement | ||
22 | 24 | ||
23 | @Injectable() | 25 | @Injectable() |
24 | export class CustomMarkupService { | 26 | export class CustomMarkupService { |
25 | private builders: { [ selector: string ]: BuilderFunction } = { | 27 | private angularBuilders: { [ selector: string ]: AngularBuilderFunction } = { |
26 | 'peertube-button': el => this.buttonBuilder(el), | 28 | 'peertube-button': el => this.buttonBuilder(el), |
27 | 'peertube-video-embed': el => this.embedBuilder(el, 'video'), | 29 | 'peertube-video-embed': el => this.embedBuilder(el, 'video'), |
28 | 'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'), | 30 | 'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'), |
@@ -32,6 +34,10 @@ export class CustomMarkupService { | |||
32 | 'peertube-videos-list': el => this.videosListBuilder(el) | 34 | 'peertube-videos-list': el => this.videosListBuilder(el) |
33 | } | 35 | } |
34 | 36 | ||
37 | private htmlBuilders: { [ selector: string ]: HTMLBuilderFunction } = { | ||
38 | 'peertube-container': el => this.containerBuilder(el) | ||
39 | } | ||
40 | |||
35 | private customMarkdownRenderer: (text: string) => Promise<HTMLElement> | 41 | private customMarkdownRenderer: (text: string) => Promise<HTMLElement> |
36 | 42 | ||
37 | constructor ( | 43 | constructor ( |
@@ -51,11 +57,24 @@ export class CustomMarkupService { | |||
51 | const rootElement = document.createElement('div') | 57 | const rootElement = document.createElement('div') |
52 | rootElement.innerHTML = html | 58 | rootElement.innerHTML = html |
53 | 59 | ||
54 | for (const selector of this.getSupportedTags()) { | 60 | for (const selector of Object.keys(this.htmlBuilders)) { |
61 | rootElement.querySelectorAll(selector) | ||
62 | .forEach((e: HTMLElement) => { | ||
63 | try { | ||
64 | const element = this.execHTMLBuilder(selector, e) | ||
65 | // Insert as first child | ||
66 | e.insertBefore(element, e.firstChild) | ||
67 | } catch (err) { | ||
68 | console.error('Cannot inject component %s.', selector, err) | ||
69 | } | ||
70 | }) | ||
71 | } | ||
72 | |||
73 | for (const selector of Object.keys(this.angularBuilders)) { | ||
55 | rootElement.querySelectorAll(selector) | 74 | rootElement.querySelectorAll(selector) |
56 | .forEach((e: HTMLElement) => { | 75 | .forEach((e: HTMLElement) => { |
57 | try { | 76 | try { |
58 | const component = this.execBuilder(selector, e) | 77 | const component = this.execAngularBuilder(selector, e) |
59 | 78 | ||
60 | this.dynamicElementService.injectElement(e, component) | 79 | this.dynamicElementService.injectElement(e, component) |
61 | } catch (err) { | 80 | } catch (err) { |
@@ -68,11 +87,16 @@ export class CustomMarkupService { | |||
68 | } | 87 | } |
69 | 88 | ||
70 | private getSupportedTags () { | 89 | private getSupportedTags () { |
71 | return Object.keys(this.builders) | 90 | return Object.keys(this.angularBuilders) |
91 | .concat(Object.keys(this.htmlBuilders)) | ||
72 | } | 92 | } |
73 | 93 | ||
74 | private execBuilder (selector: string, el: HTMLElement) { | 94 | private execHTMLBuilder (selector: string, el: HTMLElement) { |
75 | return this.builders[selector](el) | 95 | return this.htmlBuilders[selector](el) |
96 | } | ||
97 | |||
98 | private execAngularBuilder (selector: string, el: HTMLElement) { | ||
99 | return this.angularBuilders[selector](el) | ||
76 | } | 100 | } |
77 | 101 | ||
78 | private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') { | 102 | private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') { |
@@ -131,8 +155,6 @@ export class CustomMarkupService { | |||
131 | const component = this.dynamicElementService.createElement(VideosListMarkupComponent) | 155 | const component = this.dynamicElementService.createElement(VideosListMarkupComponent) |
132 | 156 | ||
133 | const model = { | 157 | const model = { |
134 | title: data.title, | ||
135 | description: data.description, | ||
136 | sort: data.sort, | 158 | sort: data.sort, |
137 | categoryOneOf: this.buildArrayNumber(data.categoryOneOf), | 159 | categoryOneOf: this.buildArrayNumber(data.categoryOneOf), |
138 | languageOneOf: this.buildArrayString(data.languageOneOf), | 160 | languageOneOf: this.buildArrayString(data.languageOneOf), |
@@ -144,6 +166,31 @@ export class CustomMarkupService { | |||
144 | return component | 166 | return component |
145 | } | 167 | } |
146 | 168 | ||
169 | private containerBuilder (el: HTMLElement) { | ||
170 | const data = el.dataset as ContainerMarkupData | ||
171 | |||
172 | const root = document.createElement('div') | ||
173 | root.classList.add('peertube-container') | ||
174 | |||
175 | if (data.width) { | ||
176 | root.setAttribute('width', data.width) | ||
177 | } | ||
178 | |||
179 | if (data.title) { | ||
180 | const titleElement = document.createElement('h4') | ||
181 | titleElement.innerText = data.title | ||
182 | root.appendChild(titleElement) | ||
183 | } | ||
184 | |||
185 | if (data.description) { | ||
186 | const descriptionElement = document.createElement('div') | ||
187 | descriptionElement.innerText = data.description | ||
188 | root.appendChild(descriptionElement) | ||
189 | } | ||
190 | |||
191 | return root | ||
192 | } | ||
193 | |||
147 | private buildNumber (value: string) { | 194 | private buildNumber (value: string) { |
148 | if (!value) return undefined | 195 | if (!value) return undefined |
149 | 196 | ||