X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=client%2Fsrc%2Fapp%2Fshared%2Fshared-custom-markup%2Fcustom-markup.service.ts;h=db5f64ee80bc6b72ed2a8f4c5ee023c1b8185fa7;hb=9105634f16e5dfc66df198f23dbfae77dff2d821;hp=09414da95d8fbc0d2a0ad9bb93056af435879f80;hpb=4d7ce9218a3f695bf3d013cbdce1c5c6a5221927;p=github%2FChocobozzz%2FPeerTube.git 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 09414da95..db5f64ee8 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,24 +3,29 @@ import { MarkdownService } from '@app/core' import { ButtonMarkupData, ChannelMiniatureMarkupData, + ContainerMarkupData, EmbedMarkupData, PlaylistMiniatureMarkupData, + VideoFilter, VideoMiniatureMarkupData, VideosListMarkupData } from '@shared/models' -import { ButtonMarkupComponent } from './button-markup.component' -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' +import { + ButtonMarkupComponent, + ChannelMiniatureMarkupComponent, + EmbedMarkupComponent, + PlaylistMiniatureMarkupComponent, + VideoMiniatureMarkupComponent, + VideosListMarkupComponent +} from './peertube-custom-tags' -type BuilderFunction = (el: HTMLElement) => ComponentRef +type AngularBuilderFunction = (el: HTMLElement) => ComponentRef +type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement @Injectable() export class CustomMarkupService { - private builders: { [ selector: string ]: BuilderFunction } = { + private angularBuilders: { [ selector: string ]: AngularBuilderFunction } = { 'peertube-button': el => this.buttonBuilder(el), 'peertube-video-embed': el => this.embedBuilder(el, 'video'), 'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'), @@ -30,10 +35,22 @@ export class CustomMarkupService { 'peertube-videos-list': el => this.videosListBuilder(el) } + private htmlBuilders: { [ selector: string ]: HTMLBuilderFunction } = { + 'peertube-container': el => this.containerBuilder(el) + } + + private customMarkdownRenderer: (text: string) => Promise + constructor ( private dynamicElementService: DynamicElementService, private markdown: MarkdownService - ) { } + ) { + this.customMarkdownRenderer = async (text: string) => this.buildElement(text) + } + + getCustomMarkdownRenderer () { + return this.customMarkdownRenderer + } async buildElement (text: string) { const html = await this.markdown.customPageMarkdownToHTML(text, this.getSupportedTags()) @@ -41,11 +58,24 @@ export class CustomMarkupService { const rootElement = document.createElement('div') rootElement.innerHTML = html - for (const selector of this.getSupportedTags()) { + for (const selector of Object.keys(this.htmlBuilders)) { rootElement.querySelectorAll(selector) .forEach((e: HTMLElement) => { try { - const component = this.execBuilder(selector, e) + const element = this.execHTMLBuilder(selector, e) + // Insert as first child + e.insertBefore(element, e.firstChild) + } catch (err) { + console.error('Cannot inject component %s.', selector, err) + } + }) + } + + for (const selector of Object.keys(this.angularBuilders)) { + rootElement.querySelectorAll(selector) + .forEach((e: HTMLElement) => { + try { + const component = this.execAngularBuilder(selector, e) this.dynamicElementService.injectElement(e, component) } catch (err) { @@ -58,11 +88,16 @@ export class CustomMarkupService { } private getSupportedTags () { - return Object.keys(this.builders) + return Object.keys(this.angularBuilders) + .concat(Object.keys(this.htmlBuilders)) } - private execBuilder (selector: string, el: HTMLElement) { - return this.builders[selector](el) + private execHTMLBuilder (selector: string, el: HTMLElement) { + return this.htmlBuilders[selector](el) + } + + private execAngularBuilder (selector: string, el: HTMLElement) { + return this.angularBuilders[selector](el) } private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') { @@ -74,15 +109,6 @@ export class CustomMarkupService { 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) @@ -116,16 +142,30 @@ export class CustomMarkupService { return component } + private videoMiniatureBuilder (el: HTMLElement) { + const data = el.dataset as VideoMiniatureMarkupData + const component = this.dynamicElementService.createElement(VideoMiniatureMarkupComponent) + + const model = { + uuid: data.uuid, + onlyDisplayTitle: this.buildBoolean(data.onlyDisplayTitle) ?? false + } + + this.dynamicElementService.setModel(component, model) + + 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), + onlyDisplayTitle: this.buildBoolean(data.onlyDisplayTitle) ?? false, + sort: data.sort || '-publishedAt', + categoryOneOf: this.buildArrayNumber(data.categoryOneOf) ?? [], + languageOneOf: this.buildArrayString(data.languageOneOf) ?? [], + filter: this.buildBoolean(data.onlyLocal) ? 'local' as VideoFilter : undefined, count: this.buildNumber(data.count) || 10 } @@ -134,6 +174,31 @@ export class CustomMarkupService { return component } + private containerBuilder (el: HTMLElement) { + const data = el.dataset as ContainerMarkupData + + const root = document.createElement('div') + root.classList.add('peertube-container') + + if (data.width) { + root.setAttribute('width', data.width) + } + + if (data.title) { + const titleElement = document.createElement('h4') + titleElement.innerText = data.title + root.appendChild(titleElement) + } + + if (data.description) { + const descriptionElement = document.createElement('div') + descriptionElement.innerText = data.description + root.appendChild(descriptionElement) + } + + return root + } + private buildNumber (value: string) { if (!value) return undefined