Correctly truncate HTML

We can because we don't use the video truncated description since v5.0
This commit is contained in:
Chocobozzz 2023-08-17 14:26:49 +02:00
parent e4f82eaa8b
commit c5f8dc0533
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
12 changed files with 58 additions and 96 deletions

View File

@ -55,7 +55,7 @@
<my-markdown-textarea
formControlName="description" [markdownVideo]="videoToUpdate"
[formError]="formErrors.description" [truncate]="250"
[formError]="formErrors.description" [truncateTo3Lines]="true"
></my-markdown-textarea>
</div>
</div>

View File

@ -1,25 +1,26 @@
<div class="video-info-description">
<div
#descriptionHTML
class="video-info-description-html"
[innerHTML]="getHTMLDescription()"
[ngClass]="{ 'ellipsis-multiline-3': !completeDescriptionShown }"
[innerHTML]="videoHTMLDescription"
(timestampClicked)="onTimestampClicked($event)"
myTimestampRouteTransformer
></div>
<button
*ngIf="completeDescriptionShown === false && video.description?.length >= 250"
(click)="showMoreDescription()" class="video-info-description-more button-unstyle"
*ngIf="(hasEllipsis() && !completeDescriptionShown) || completeDescriptionShown"
(click)="completeDescriptionShown = !completeDescriptionShown"
class="video-info-description-more button-unstyle"
>
<ng-container *ngIf="!completeDescriptionShown">
<ng-container i18n>Show more</ng-container>
<span *ngIf="descriptionLoading === false" class="chevron-down"></span>
<my-loader size="sm" class="description-loading" [loading]="descriptionLoading"></my-loader>
</button>
<span class="chevron-down"></span>
</ng-container>
<button
*ngIf="completeDescriptionShown === true"
(click)="showLessDescription()" class="video-info-description-more button-unstyle"
>
<ng-container *ngIf="completeDescriptionShown">
<ng-container i18n>Show less</ng-container>
<span *ngIf="descriptionLoading === false" class="chevron-up"></span>
<span class="chevron-up"></span>
</ng-container>
</button>
</div>

View File

@ -11,9 +11,15 @@
.video-info-description-html {
@include peertube-word-wrap;
::ng-deep a {
::ng-deep {
a {
text-decoration: none;
}
p:last-child {
margin-bottom: 0;
}
}
}
.description-loading {
@ -21,10 +27,12 @@
}
.video-info-description-more {
@include font-size(14px);
cursor: pointer;
font-weight: $font-semibold;
color: pvar(--greyForegroundColor);
font-size: 14px;
margin-top: 1rem;
}
}

View File

@ -1,7 +1,6 @@
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'
import { MarkdownService, Notifier } from '@app/core'
import { VideoDetails, VideoService } from '@app/shared/shared-main'
import { logger } from '@root-helpers/logger'
import { Component, EventEmitter, Input, OnChanges, Output, ViewChild, ElementRef } from '@angular/core'
import { MarkdownService } from '@app/core'
import { VideoDetails } from '@app/shared/shared-main'
@Component({
selector: 'my-video-description',
@ -9,36 +8,34 @@ import { logger } from '@root-helpers/logger'
styleUrls: [ './video-description.component.scss' ]
})
export class VideoDescriptionComponent implements OnChanges {
@ViewChild('descriptionHTML') descriptionHTML: ElementRef<HTMLElement>
@Input() video: VideoDetails
@Output() timestampClicked = new EventEmitter<number>()
descriptionLoading = false
completeDescriptionShown = false
completeVideoDescriptionLoaded = false
videoHTMLTruncatedDescription = ''
videoHTMLDescription = ''
constructor (
private videoService: VideoService,
private notifier: Notifier,
private markdownService: MarkdownService
) { }
ngOnChanges () {
this.descriptionLoading = false
this.completeDescriptionShown = false
this.setVideoDescriptionHTML()
}
showMoreDescription () {
if (!this.completeVideoDescriptionLoaded) {
return this.loadCompleteDescription()
hasEllipsis () {
const el = this.descriptionHTML?.nativeElement
if (!el) return false
return el.offsetHeight < el.scrollHeight
}
showMoreDescription () {
this.completeDescriptionShown = true
}
@ -46,51 +43,13 @@ export class VideoDescriptionComponent implements OnChanges {
this.completeDescriptionShown = false
}
loadCompleteDescription () {
this.descriptionLoading = true
this.videoService.loadCompleteDescription(this.video.descriptionPath)
.subscribe({
next: description => {
this.completeDescriptionShown = true
this.descriptionLoading = false
this.video.description = description
this.setVideoDescriptionHTML()
.catch(err => logger.error(err))
},
error: err => {
this.descriptionLoading = false
this.notifier.error(err.message)
}
})
}
onTimestampClicked (timestamp: number) {
this.timestampClicked.emit(timestamp)
}
getHTMLDescription () {
if (this.completeDescriptionShown) {
return this.videoHTMLDescription
}
return this.videoHTMLTruncatedDescription
}
private async setVideoDescriptionHTML () {
{
const html = await this.markdownService.textMarkdownToHTML({ markdown: this.video.description })
this.videoHTMLDescription = this.markdownService.processVideoTimestamps(this.video.shortUUID, html)
}
{
const html = await this.markdownService.textMarkdownToHTML({ markdown: this.video.truncatedDescription })
this.videoHTMLTruncatedDescription = this.markdownService.processVideoTimestamps(this.video.shortUUID, html)
}
}
}

View File

@ -138,8 +138,7 @@ export class MarkdownService {
}
}
let html = this.markdownParsers[name].render(markdown)
html = this.avoidTruncatedTags(html)
const html = this.markdownParsers[name].render(markdown)
if (config.escape) return this.htmlRenderer.toSafeHtml(html, additionalAllowedTags)
@ -181,11 +180,4 @@ export class MarkdownService {
return defaultRender(tokens, index, options, env, self)
}
}
private avoidTruncatedTags (html: string) {
return html.replace(/\*\*?([^*]+)$/, '$1')
.replace(/<a[^>]+>([^<]+)<\/a>\s*...((<\/p>)|(<\/li>)|(<\/strong>))?$/mi, '$1...')
.replace(/\[[^\]]+\]\(([^)]+)$/m, '$1')
.replace(/\s?\[[^\]]+\]?[.]{3}<\/p>$/m, '...</p>')
}
}

View File

@ -96,7 +96,7 @@
<strong i18n>Comment:</strong>
</div>
<div [innerHTML]="abuse.commentHtml"></div>
<div [innerHTML]="abuse.commentHTML"></div>
</div>
</div>
</div>

View File

@ -90,7 +90,8 @@
<ng-container *ngIf="abuse.comment">
<td>
<a [href]="getCommentUrl(abuse)" [innerHTML]="abuse.truncatedCommentHtml" class="table-comment-link"
<a
[href]="getCommentUrl(abuse)" [innerHTML]="abuse.commentHTML" class="table-comment-link ellipsis-multiline-1"
[title]="abuse.comment.video.name" target="_blank" rel="noopener noreferrer"
></a>

View File

@ -1,5 +1,4 @@
import * as debug from 'debug'
import truncate from 'lodash-es/truncate'
import { SortMeta } from 'primeng/api'
import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
@ -211,11 +210,9 @@ export class AbuseListTableComponent extends RestTable implements OnInit {
if (abuse.comment) {
if (abuse.comment.deleted) {
abuse.truncatedCommentHtml = abuse.commentHtml = $localize`Deleted comment`
abuse.commentHTML = $localize`Deleted comment`
} else {
const truncated = truncate(abuse.comment.text, { length: 100 })
abuse.truncatedCommentHtml = await this.markdownRenderer.textMarkdownToHTML({ markdown: truncated, withHtml: true })
abuse.commentHtml = await this.markdownRenderer.textMarkdownToHTML({ markdown: abuse.comment.text, withHtml: true })
abuse.commentHTML = await this.markdownRenderer.textMarkdownToHTML({ markdown: abuse.comment.text, withHtml: true })
}
}

View File

@ -12,8 +12,7 @@ export type ProcessedAbuse = AdminAbuse & {
reporterAccount?: Account
flaggedAccount?: Account
truncatedCommentHtml?: string
commentHtml?: string
commentHTML?: string
video: AdminAbuse['video'] & {
channel: AdminAbuse['video']['channel'] & {

View File

@ -8,11 +8,11 @@
</textarea>
<div ngbNav #nav="ngbNav" class="nav-pills nav-preview">
<ng-container ngbNavItem *ngIf="truncate !== undefined">
<ng-container ngbNavItem *ngIf="truncateTo3Lines">
<a ngbNavLink i18n>Truncated preview</a>
<ng-template ngbNavContent>
<div [innerHTML]="truncatedPreviewHTML"></div>
<div class="ellipsis-multiline-3" [innerHTML]="previewHTML"></div>
</ng-template>
</ng-container>

View File

@ -1,4 +1,3 @@
import truncate from 'lodash-es/truncate'
import { Subject } from 'rxjs'
import { debounceTime, distinctUntilChanged } from 'rxjs/operators'
import { ViewportScroller } from '@angular/common'
@ -26,7 +25,7 @@ export class MarkdownTextareaComponent implements ControlValueAccessor, OnInit {
@Input() formError: string
@Input() truncate: number
@Input() truncateTo3Lines: boolean
@Input() markdownType: 'text' | 'enhanced' | 'to-unsafe-html' = 'text'
@Input() customMarkdownRenderer?: (text: string) => Promise<string | HTMLElement>
@ -42,7 +41,6 @@ export class MarkdownTextareaComponent implements ControlValueAccessor, OnInit {
@ViewChild('textarea') textareaElement: ElementRef
@ViewChild('previewElement') previewElement: ElementRef
truncatedPreviewHTML: SafeHtml | string = ''
previewHTML: SafeHtml | string = ''
isMaximized = false
@ -129,7 +127,6 @@ export class MarkdownTextareaComponent implements ControlValueAccessor, OnInit {
private async updatePreviews () {
if (this.content === null || this.content === undefined) return
this.truncatedPreviewHTML = await this.markdownRender(truncate(this.content, { length: this.truncate }))
this.previewHTML = await this.markdownRender(this.content)
}

View File

@ -36,6 +36,10 @@
overflow: hidden;
}
.ellipsis-multiline-1 {
@include ellipsis-multiline(1);
}
.ellipsis-multiline-2 {
@include ellipsis-multiline(2);
}
@ -45,3 +49,7 @@
}
// ---------------------------------------------------------------------------
.ellipsis {
@include ellipsis;
}