diff options
author | Chocobozzz <me@florianbigard.com> | 2021-05-27 16:12:41 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-05-27 16:12:41 +0200 |
commit | 8f608a4cb22ab232cfab20665050764b38bac9c7 (patch) | |
tree | 6a6785aae79bf5939ad7b7a50a1bd8031268d2b4 /client/src/app/shared/shared-custom-markup/custom-markup.service.ts | |
parent | 030ccfce59a8cb8f2fee6ea8dd363ba635c5c5c2 (diff) | |
parent | c215e627b575d2c4085ccb222f4ca8d0237b7552 (diff) | |
download | PeerTube-8f608a4cb22ab232cfab20665050764b38bac9c7.tar.gz PeerTube-8f608a4cb22ab232cfab20665050764b38bac9c7.tar.zst PeerTube-8f608a4cb22ab232cfab20665050764b38bac9c7.zip |
Merge branch 'develop' into shorter-URLs-channels-accounts
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 | 136 |
1 files changed, 136 insertions, 0 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 new file mode 100644 index 000000000..ffaf15710 --- /dev/null +++ b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts | |||
@@ -0,0 +1,136 @@ | |||
1 | import { ComponentRef, Injectable } from '@angular/core' | ||
2 | import { MarkdownService } from '@app/core' | ||
3 | import { | ||
4 | ChannelMiniatureMarkupData, | ||
5 | EmbedMarkupData, | ||
6 | PlaylistMiniatureMarkupData, | ||
7 | VideoMiniatureMarkupData, | ||
8 | VideosListMarkupData | ||
9 | } from '@shared/models' | ||
10 | import { ChannelMiniatureMarkupComponent } from './channel-miniature-markup.component' | ||
11 | import { DynamicElementService } from './dynamic-element.service' | ||
12 | import { EmbedMarkupComponent } from './embed-markup.component' | ||
13 | import { PlaylistMiniatureMarkupComponent } from './playlist-miniature-markup.component' | ||
14 | import { VideoMiniatureMarkupComponent } from './video-miniature-markup.component' | ||
15 | import { VideosListMarkupComponent } from './videos-list-markup.component' | ||
16 | |||
17 | type BuilderFunction = (el: HTMLElement) => ComponentRef<any> | ||
18 | |||
19 | @Injectable() | ||
20 | export class CustomMarkupService { | ||
21 | private builders: { [ selector: string ]: BuilderFunction } = { | ||
22 | 'peertube-video-embed': el => this.embedBuilder(el, 'video'), | ||
23 | 'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'), | ||
24 | 'peertube-video-miniature': el => this.videoMiniatureBuilder(el), | ||
25 | 'peertube-playlist-miniature': el => this.playlistMiniatureBuilder(el), | ||
26 | 'peertube-channel-miniature': el => this.channelMiniatureBuilder(el), | ||
27 | 'peertube-videos-list': el => this.videosListBuilder(el) | ||
28 | } | ||
29 | |||
30 | constructor ( | ||
31 | private dynamicElementService: DynamicElementService, | ||
32 | private markdown: MarkdownService | ||
33 | ) { } | ||
34 | |||
35 | async buildElement (text: string) { | ||
36 | const html = await this.markdown.customPageMarkdownToHTML(text, this.getSupportedTags()) | ||
37 | |||
38 | const rootElement = document.createElement('div') | ||
39 | rootElement.innerHTML = html | ||
40 | |||
41 | for (const selector of this.getSupportedTags()) { | ||
42 | rootElement.querySelectorAll(selector) | ||
43 | .forEach((e: HTMLElement) => { | ||
44 | try { | ||
45 | const component = this.execBuilder(selector, e) | ||
46 | |||
47 | this.dynamicElementService.injectElement(e, component) | ||
48 | } catch (err) { | ||
49 | console.error('Cannot inject component %s.', selector, err) | ||
50 | } | ||
51 | }) | ||
52 | } | ||
53 | |||
54 | return rootElement | ||
55 | } | ||
56 | |||
57 | private getSupportedTags () { | ||
58 | return Object.keys(this.builders) | ||
59 | } | ||
60 | |||
61 | private execBuilder (selector: string, el: HTMLElement) { | ||
62 | return this.builders[selector](el) | ||
63 | } | ||
64 | |||
65 | private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') { | ||
66 | const data = el.dataset as EmbedMarkupData | ||
67 | const component = this.dynamicElementService.createElement(EmbedMarkupComponent) | ||
68 | |||
69 | this.dynamicElementService.setModel(component, { uuid: data.uuid, type }) | ||
70 | |||
71 | return component | ||
72 | } | ||
73 | |||
74 | private videoMiniatureBuilder (el: HTMLElement) { | ||
75 | const data = el.dataset as VideoMiniatureMarkupData | ||
76 | const component = this.dynamicElementService.createElement(VideoMiniatureMarkupComponent) | ||
77 | |||
78 | this.dynamicElementService.setModel(component, { uuid: data.uuid }) | ||
79 | |||
80 | return component | ||
81 | } | ||
82 | |||
83 | private playlistMiniatureBuilder (el: HTMLElement) { | ||
84 | const data = el.dataset as PlaylistMiniatureMarkupData | ||
85 | const component = this.dynamicElementService.createElement(PlaylistMiniatureMarkupComponent) | ||
86 | |||
87 | this.dynamicElementService.setModel(component, { uuid: data.uuid }) | ||
88 | |||
89 | return component | ||
90 | } | ||
91 | |||
92 | private channelMiniatureBuilder (el: HTMLElement) { | ||
93 | const data = el.dataset as ChannelMiniatureMarkupData | ||
94 | const component = this.dynamicElementService.createElement(ChannelMiniatureMarkupComponent) | ||
95 | |||
96 | this.dynamicElementService.setModel(component, { name: data.name }) | ||
97 | |||
98 | return component | ||
99 | } | ||
100 | |||
101 | private videosListBuilder (el: HTMLElement) { | ||
102 | const data = el.dataset as VideosListMarkupData | ||
103 | const component = this.dynamicElementService.createElement(VideosListMarkupComponent) | ||
104 | |||
105 | const model = { | ||
106 | title: data.title, | ||
107 | description: data.description, | ||
108 | sort: data.sort, | ||
109 | categoryOneOf: this.buildArrayNumber(data.categoryOneOf), | ||
110 | languageOneOf: this.buildArrayString(data.languageOneOf), | ||
111 | count: this.buildNumber(data.count) || 10 | ||
112 | } | ||
113 | |||
114 | this.dynamicElementService.setModel(component, model) | ||
115 | |||
116 | return component | ||
117 | } | ||
118 | |||
119 | private buildNumber (value: string) { | ||
120 | if (!value) return undefined | ||
121 | |||
122 | return parseInt(value, 10) | ||
123 | } | ||
124 | |||
125 | private buildArrayNumber (value: string) { | ||
126 | if (!value) return undefined | ||
127 | |||
128 | return value.split(',').map(v => parseInt(v, 10)) | ||
129 | } | ||
130 | |||
131 | private buildArrayString (value: string) { | ||
132 | if (!value) return undefined | ||
133 | |||
134 | return value.split(',') | ||
135 | } | ||
136 | } | ||