feat(parser): Text#toHTML (#300)

Added support to render Text nodes as HTML for use in web applications.
This commit is contained in:
Daniel Wykerd
2023-02-01 21:27:59 +02:00
committed by GitHub
parent f62c66db39
commit e82e23dfbb
4 changed files with 62 additions and 2 deletions

View File

@@ -1,6 +1,7 @@
import { escape, Run } from './Text';
import Thumbnail from './Thumbnail';
class EmojiRun {
class EmojiRun implements Run {
text: string;
emoji: {
emoji_id: string;
@@ -24,6 +25,15 @@ class EmojiRun {
is_custom: !!data.emoji?.isCustomEmoji
};
}
toString() {
return this.text;
}
toHTML(): string {
const escaped_text = escape(this.text);
return `<img src="${this.emoji.image[0].url}" alt="${escaped_text}" title="${escaped_text}" style="display: inline-block; vertical-align: text-top; height: var(--yt-emoji-size, 1rem); width: var(--yt-emoji-size, 1rem);" loading="lazy" crossorigin="anonymous" />`;
}
}
export default EmojiRun;

View File

@@ -1,6 +1,21 @@
import TextRun from './TextRun';
import EmojiRun from './EmojiRun';
export interface Run {
text: string;
toString(): string;
toHTML(): string;
}
export function escape(text: string) {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
class Text {
text: string;
runs;
@@ -17,6 +32,10 @@ class Text {
}
}
toHTML() {
return this.runs ? this.runs.map((run) => run.toHTML()).join('') : this.text;
}
toString() {
return this.text;
}

View File

@@ -1,6 +1,7 @@
import NavigationEndpoint from '../NavigationEndpoint';
import { escape, Run } from './Text';
class TextRun {
class TextRun implements Run {
text: string;
endpoint: NavigationEndpoint | undefined;
bold: boolean;
@@ -14,6 +15,25 @@ class TextRun {
this.strikethrough = Boolean(data.strikethrough);
this.endpoint = data.navigationEndpoint ? new NavigationEndpoint(data.navigationEndpoint) : undefined;
}
toString() {
return this.text;
}
toHTML(): string {
const tags: string[] = [];
if (this.bold) tags.push('b');
if (this.italics) tags.push('i');
if (this.strikethrough) tags.push('s');
const escaped_text = escape(this.text);
const styled_text = tags.map((tag) => `<${tag}>`).join('') + escaped_text + tags.map((tag) => `</${tag}>`).join('');
const wrapped_text = `<span style="white-space: pre-wrap;">${styled_text}</span>`;
if (this.endpoint) {
const url = this.endpoint.toURL();
if (url) return `<a href="${url}">${wrapped_text}</a>`;
}
return wrapped_text;
}
}
export default TextRun;