Add Youtube embeds

This will embed a youtube video inline on the page. Hopefully it works!

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-07-29 19:59:10 -07:00
parent b7cc4c5681
commit b84ca6d84f
4 changed files with 56 additions and 3 deletions

View File

@@ -345,6 +345,27 @@ $(window).on("load", () => {
$(e.target).attr("src", thumbUrl); $(e.target).attr("src", thumbUrl);
} }
}); });
$(".youtube_embed_link").on("click", (e) => {
e.preventDefault();
let fullEnt = $(e.target).parents(".youtube_embed");
let frame = fullEnt.find(".youtube_embed_frame");
if (frame.length) {
frame.remove();
} else {
let hash = $(e.target).attr("data-yt-hash");
let embed = $("<span>")
.attr("class", "youtube_embed_frame")
.append("<br/>")
.append(
$("<iframe>")
.attr("src", "https://www.youtube.com/embed/" + hash)
.attr("frameborder", "0")
.attr("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture")
);
fullEnt.find(".youtube_embed_container").append(embed);
}
});
}); });
// Load event that actually does stuff // Load event that actually does stuff

View File

@@ -169,6 +169,9 @@ th {
right: 0px; right: 0px;
} }
/* Youtube embeds */
/* Spoilers */ /* Spoilers */
.spoiler { .spoiler {

View File

@@ -1,4 +1,5 @@
import re import re
from typing import Match, Pattern
from django import template from django import template
from board.models import Post from board.models import Post
@@ -6,6 +7,9 @@ from board.models import Post
REPLY_START_RE = re.compile(r"^&gt;&gt;\d+") REPLY_START_RE = re.compile(r"^&gt;&gt;\d+")
REPLY_RE = re.compile(r"&gt;&gt;\d+") REPLY_RE = re.compile(r"&gt;&gt;\d+")
QUOTE_RE = re.compile(r"&gt;.+$") QUOTE_RE = re.compile(r"&gt;.+$")
YOUTUBE_RE = re.compile(
r"https?://(((www\.)?youtube\.com/watch\?v=)|(youtu\.be/(watch\?v=)?))(?P<yt_hash>[a-zA-Z0-9_\-]{11})"
)
register = template.Library() register = template.Library()
@@ -19,9 +23,12 @@ def htmlspecialchars(t: str):
class ReplyBuilder: class ReplyBuilder:
def __init__(self, text: str, parse_spoilers: bool = False): def __init__(
self, text: str, parse_spoilers: bool = False, parse_youtube: bool = True
):
self.text = text self.text = text
self.parse_spoilers = parse_spoilers self.parse_spoilers = parse_spoilers
self.parse_youtube = parse_youtube
self.index = 0 self.index = 0
self.final = "" self.final = ""
@@ -46,8 +53,12 @@ class ReplyBuilder:
def adv(self, n=1): def adv(self, n=1):
self.index += n self.index += n
def matches(self, prefix: str) -> bool: def matches(self, prefix: str | Pattern) -> bool | Match:
return self.remain[: len(prefix)] == prefix if isinstance(prefix, str):
return self.remain.startswith(prefix)
else:
mat = prefix.match(self.remain)
return mat or False
def build(self) -> str: def build(self) -> str:
while self.c: while self.c:
@@ -60,6 +71,12 @@ class ReplyBuilder:
self.adv(9) self.adv(9)
elif self.parse_spoilers and self.matches("[spoiler]"): elif self.parse_spoilers and self.matches("[spoiler]"):
self.do_spoiler() self.do_spoiler()
elif self.parse_youtube and (mat := self.matches(YOUTUBE_RE)):
assert isinstance(mat, Match)
url = mat[0]
yt_hash = mat["yt_hash"]
self.final += f'<span class="youtube_embed"><span class="youtube_embed_container">{url} [<a class="youtube_embed_link" data-yt-hash="{yt_hash}" href="{url}">Embed</a>]</span></span>'
self.adv(len(url))
else: else:
self.final += self.c self.final += self.c
self.adv() self.adv()

View File

@@ -103,3 +103,15 @@ what happened to the 1 2 3 4 5 6 7 8 9
for input, output in expected: for input, output in expected:
rb = ReplyBuilder(input.strip(), parse_spoilers=True) rb = ReplyBuilder(input.strip(), parse_spoilers=True)
self.assertEquals(rb.build(), output) self.assertEquals(rb.build(), output)
def test_youtube_embed(self):
expected = [
(
"https://www.youtube.com/watch?v=O_3_-UrhZH0",
'<span class="youtube_embed"><span class="youtube_embed_container">https://www.youtube.com/watch?v=O_3_-UrhZH0 [<a class="youtube_embed_link" data-yt-hash="O_3_-UrhZH0" href="https://www.youtube.com/watch?v=O_3_-UrhZH0">Embed</a>]</span></span>',
),
]
for input, output in expected:
rb = ReplyBuilder(input.strip())
self.assertEquals(rb.build(), output)