feature: file uploads and audio embedding

This commit is contained in:
Andy Burke 2025-08-20 11:48:16 -07:00
parent 2224e1abe0
commit 4c0a8bb700
7 changed files with 105 additions and 22 deletions

View file

@ -2,7 +2,7 @@
// watch out for places we need to set `lastIndex` ... :frown:
const URL_MATCHING_REGEX =
/(?:(?<protocol>[a-zA-Z]+):\/\/)?(?:(?<auth>(?<username>\S.+)\:(?<password>.+))\@)?(?<host>(?:(?<hostname>[-a-zA-Z0-9\.]+)\.)?(?<domain>[-a-zA-Z0-9]+?\.(?<tld>[-a-zA-Z0-9]{2,64}))(?:\:(?<port>[0-9]{1,6}))?)\b(?<path>[-a-zA-Z0-9@:%_{}\[\]<>\(\)\+.~&\/="]*?(?<extension>\.[^\.?/#"]+)?)(?:\?(?<query>[a-zA-Z0-9!$%&<>()*+,-\.\/\:\;\=\?\@_~"]+))?(?:#(?<hash>[a-zA-Z0-9!$&'()*+,-\.\/\:\;\=\?\@_~"]*?))?(?:$|\s)/gim;
/(?:(?<protocol>[a-zA-Z]+):)?(?:\/\/)?(?:(?<auth>(?<username>\S.+)\:(?<password>.+))\@)?(?<host>(?:(?<hostname>[-a-zA-Z0-9\.]+)\.)?(?<domain>(?:[-a-zA-Z0-9]+?\.(?<tld>[-a-zA-Z0-9]{2,64}))|localhost)(?:\:(?<port>[0-9]{1,6}))?)\b(?<path>[-a-zA-Z0-9@:%_{}\[\]<>\(\)\+.~&\/="]*?(?<extension>\.[^\.?/#"\n<>]+)?)(?:\?(?<query>[a-zA-Z0-9!$%&<>()*+,-\.\/\:\;\=\?\@_~"]+))?(?:#(?<hash>[a-zA-Z0-9!$&'()*+,-\.\/\:\;\=\?\@_~"]*?))?(?:$|\s)/gim;
const VIDEO_ID_EXTRACTOR =
/(?<video_domain>vimeo\.com|youtu(?:be\.com|\.be|be\.googleapis\.com))(?:\/(?<action>video|embed|watch|shorts|v))?.*(?:(?:\/|v=)(?<video_id>[A-Za-z0-9._%-]*))\S*/gi;
@ -159,8 +159,14 @@ const URL_MATCH_HANDLERS = [
// const punycode = get_punycode();
// const punycoded_url = punycode.encode(match[0]);
console.dir({
link_info,
});
if (typeof link_info.extension === "string") {
const mime_types = get_mime_types(link_info.extension);
console.dir({
mime_types,
});
if (mime_types.length) {
if (mime_types.includes("image/gif")) {
return `<div class="embed-container image gif"><img src="${link_info.url}" alt="A gif from ${link_info.domain}" /></div>`;
@ -173,6 +179,16 @@ const URL_MATCH_HANDLERS = [
if (mime_types[0].indexOf("image") === 0) {
return `<div class="embed-container image"><img src="${link_info.url}" alt="An image from ${link_info.domain}" /></div>`;
}
if (mime_types[0].indexOf("audio") === 0) {
return `
<div class="embed-container short">
<audio controls>
<source src="${link_info.url}" type="${mime_types[0].indexOf("audio/mpeg") === 0 ? "audio/mpeg" : mime_types[0]}">
Your browser does not support the audio element.
</audio>
</div>`;
}
}
}
@ -181,7 +197,7 @@ const URL_MATCH_HANDLERS = [
];
function message_text_to_html(input) {
let html_message = input;
let html_message = (input ?? "").replace(/\n/g, "<br/>");
let match;
URL_MATCHING_REGEX.lastIndex = 0;