const get_apple_music_iframe = src => `` const get_spotify_iframe = src => `` const get_youtube_frame = src => `` const link_handlers = { 'https://music.apple.com/': link => { const embed_url = `https://embed.${link.substring(8)}` return get_apple_music_iframe(embed_url) }, 'https://open.spotify.com/': link => { const type = link.substring(link.indexOf('/', 8) + 1, link.indexOf('/', link.indexOf('/', 8) + 1)) const id = link.substring(link.lastIndexOf('/') + 1, link.indexOf('?')) const embed_url = `https://open.spotify.com/embed/${type}/${id}?utm_source=generator&theme=0` return get_spotify_iframe(embed_url) }, 'https://youtu.be/': link => { const id = link.substring(link.lastIndexOf('/') + 1, link.indexOf('?')) const embed_url = `https://www.youtube.com/embed/${id}` return get_youtube_frame(embed_url) }, } const render_body = async id => { const element = document.getElementById(id) var body = element.innerText var html = element.innerHTML // give the body a loading """animation""" while we let the fetches cook element.innerText = 'loading...' const matches = body.matchAll(/\\?[@#*]\([a-zA-Z0-9_.-]*\)/g) const cache = {} for (const match of matches) { // escaped if (match[0][0] == '\\') { html = html.replace(match[0], match[0].replace('\\', '')) } // mention else if (match[0][0] == '@') { if (cache.hasOwnProperty(match[0])) { html = html.replace(match[0], cache[match[0]]) continue } const s = await (await fetch('/api/user/get_name?username=' + match[0].substring(2, match[0].length - 1))).text() const link = document.createElement('a') link.href = `/user/${match[0].substring(2, match[0].length - 1)}` link.innerText = '@' + s cache[match[0]] = link.outerHTML html = html.replace(match[0], link.outerHTML) } // tags else if (match[0][0] == '#') { // we do not cache tags because they do not need to do // any http queries, and most people will not use the // same tag multiple times in a single post. const link = document.createElement('a') const tag = match[0].substring(2, match[0].length - 1) link.href = `/tag/${tag}` link.innerText = '#' + tag cache[match[0]] = link.outerHTML html = html.replace(match[0], link.outerHTML) } // post reference else if (match[0][0] == '*') { if (cache.hasOwnProperty(match[0])) { html = html.replace(match[0], cache[match[0]]) continue } const s = await (await fetch('/api/post/get_title?id=' + match[0].substring(2, match[0].length - 1))).text() const link = document.createElement('a') link.href = `/post/${match[0].substring(2, match[0].length - 1)}` link.innerText = '*' + s cache[match[0]] = link.outerHTML html = html.replace(match[0], link.outerHTML) } } var handled_links = [] // i am not willing to write a url regex myself, so here is where i got // this: https://stackoverflow.com/a/3809435 const links = html.matchAll(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g) for (const match of links) { const link = match[0] for (const entry of Object.entries(link_handlers)) { if (link.startsWith(entry[0])) { handled_links.push(entry[1](link)) break } } // sanatize the link before rendering it directly. no link // should ever have these three characters in them anyway. const sanatized = link .replace('<', '>') .replace('>', '<') .replace('"', '"') html = html.replace(link, `${sanatized}`) } // append handled links if (handled_links.length > 0) { // element.innerHTML += '\n\nlinks:\n' for (const handled of handled_links) { html += `\n\n${handled}` } } element.innerHTML = html }