mirror of https://github.com/Chocobozzz/PeerTube
137 lines
4.3 KiB
TypeScript
137 lines
4.3 KiB
TypeScript
import { ComponentRef, Injectable } from '@angular/core'
|
|
import { MarkdownService } from '@app/core'
|
|
import {
|
|
ChannelMiniatureMarkupData,
|
|
EmbedMarkupData,
|
|
PlaylistMiniatureMarkupData,
|
|
VideoMiniatureMarkupData,
|
|
VideosListMarkupData
|
|
} from '@shared/models'
|
|
import { ChannelMiniatureMarkupComponent } from './channel-miniature-markup.component'
|
|
import { DynamicElementService } from './dynamic-element.service'
|
|
import { EmbedMarkupComponent } from './embed-markup.component'
|
|
import { PlaylistMiniatureMarkupComponent } from './playlist-miniature-markup.component'
|
|
import { VideoMiniatureMarkupComponent } from './video-miniature-markup.component'
|
|
import { VideosListMarkupComponent } from './videos-list-markup.component'
|
|
|
|
type BuilderFunction = (el: HTMLElement) => ComponentRef<any>
|
|
|
|
@Injectable()
|
|
export class CustomMarkupService {
|
|
private builders: { [ selector: string ]: BuilderFunction } = {
|
|
'peertube-video-embed': el => this.embedBuilder(el, 'video'),
|
|
'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'),
|
|
'peertube-video-miniature': el => this.videoMiniatureBuilder(el),
|
|
'peertube-playlist-miniature': el => this.playlistMiniatureBuilder(el),
|
|
'peertube-channel-miniature': el => this.channelMiniatureBuilder(el),
|
|
'peertube-videos-list': el => this.videosListBuilder(el)
|
|
}
|
|
|
|
constructor (
|
|
private dynamicElementService: DynamicElementService,
|
|
private markdown: MarkdownService
|
|
) { }
|
|
|
|
async buildElement (text: string) {
|
|
const html = await this.markdown.customPageMarkdownToHTML(text, this.getSupportedTags())
|
|
|
|
const rootElement = document.createElement('div')
|
|
rootElement.innerHTML = html
|
|
|
|
for (const selector of this.getSupportedTags()) {
|
|
rootElement.querySelectorAll(selector)
|
|
.forEach((e: HTMLElement) => {
|
|
try {
|
|
const component = this.execBuilder(selector, e)
|
|
|
|
this.dynamicElementService.injectElement(e, component)
|
|
} catch (err) {
|
|
console.error('Cannot inject component %s.', selector, err)
|
|
}
|
|
})
|
|
}
|
|
|
|
return rootElement
|
|
}
|
|
|
|
private getSupportedTags () {
|
|
return Object.keys(this.builders)
|
|
}
|
|
|
|
private execBuilder (selector: string, el: HTMLElement) {
|
|
return this.builders[selector](el)
|
|
}
|
|
|
|
private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') {
|
|
const data = el.dataset as EmbedMarkupData
|
|
const component = this.dynamicElementService.createElement(EmbedMarkupComponent)
|
|
|
|
this.dynamicElementService.setModel(component, { uuid: data.uuid, type })
|
|
|
|
return component
|
|
}
|
|
|
|
private videoMiniatureBuilder (el: HTMLElement) {
|
|
const data = el.dataset as VideoMiniatureMarkupData
|
|
const component = this.dynamicElementService.createElement(VideoMiniatureMarkupComponent)
|
|
|
|
this.dynamicElementService.setModel(component, { uuid: data.uuid })
|
|
|
|
return component
|
|
}
|
|
|
|
private playlistMiniatureBuilder (el: HTMLElement) {
|
|
const data = el.dataset as PlaylistMiniatureMarkupData
|
|
const component = this.dynamicElementService.createElement(PlaylistMiniatureMarkupComponent)
|
|
|
|
this.dynamicElementService.setModel(component, { uuid: data.uuid })
|
|
|
|
return component
|
|
}
|
|
|
|
private channelMiniatureBuilder (el: HTMLElement) {
|
|
const data = el.dataset as ChannelMiniatureMarkupData
|
|
const component = this.dynamicElementService.createElement(ChannelMiniatureMarkupComponent)
|
|
|
|
this.dynamicElementService.setModel(component, { name: data.name })
|
|
|
|
return component
|
|
}
|
|
|
|
private videosListBuilder (el: HTMLElement) {
|
|
const data = el.dataset as VideosListMarkupData
|
|
const component = this.dynamicElementService.createElement(VideosListMarkupComponent)
|
|
|
|
const model = {
|
|
title: data.title,
|
|
description: data.description,
|
|
sort: data.sort,
|
|
categoryOneOf: this.buildArrayNumber(data.categoryOneOf),
|
|
languageOneOf: this.buildArrayString(data.languageOneOf),
|
|
count: this.buildNumber(data.count) || 10
|
|
}
|
|
|
|
this.dynamicElementService.setModel(component, model)
|
|
|
|
return component
|
|
}
|
|
|
|
private buildNumber (value: string) {
|
|
if (!value) return undefined
|
|
|
|
return parseInt(value, 10)
|
|
}
|
|
|
|
private buildArrayNumber (value: string) {
|
|
if (!value) return undefined
|
|
|
|
return value.split(',').map(v => parseInt(v, 10))
|
|
}
|
|
|
|
private buildArrayString (value: string) {
|
|
if (!value) return undefined
|
|
|
|
return value.split(',')
|
|
}
|
|
}
|