mirror of
https://github.com/face-hh/lyntr.git
synced 2026-09-14 11:06:16 +05:00
feat(link-support): show dialog when clicking on links to external websites
There are a few bugs. But I want to commit this now. It might double replace the link, which means the <a> will be wrapped in another <a> and break the HTML.
This commit is contained in:
parent
329b44b4ce
commit
a9fb44d00a
@ -14,6 +14,7 @@
|
||||
import Report from './Report.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
function getTimeElapsed(date: Date | string) {
|
||||
if (typeof date === 'string') date = new Date(date);
|
||||
@ -84,7 +85,8 @@
|
||||
let contentElement: HTMLSpanElement | null = null;
|
||||
content = content!;
|
||||
let clickingExternalLink = false;
|
||||
let openExternalLink = false;
|
||||
// I can just use this in the listener and that should work.
|
||||
let externalLink: URL | null = null;
|
||||
|
||||
const formattedDate = formatDateTooltip(createdAt);
|
||||
|
||||
@ -121,22 +123,30 @@
|
||||
|
||||
$: if (contentElement) {
|
||||
// this shouldn't have any XSS vulnerabilities. Or at least, hopefully...
|
||||
const sanitizedContent: string = DOMPurify.sanitize(content);
|
||||
const sanitizedContent: string = DOMPurify.sanitize(content, {
|
||||
USE_PROFILES: {
|
||||
html: true
|
||||
},
|
||||
});
|
||||
const links = sanitizedContent.match(/[A-z|A-Z|a-z]+:\/\/[^\s]+/gm);
|
||||
if (links)
|
||||
for (const link of links) {
|
||||
const linkHTML = `<a href="${link}" target="_blank">${link}</a>`;
|
||||
console.log("link", link, "linkHTML", linkHTML);
|
||||
// FIXME: it may "double replace" the link, which isn't good.
|
||||
contentElement.innerHTML = contentElement.innerHTML.replace(
|
||||
link,
|
||||
`<a href="${link}" class="post-link" target="_blank">${link}</a>`
|
||||
linkHTML
|
||||
);
|
||||
const a = contentElement.querySelector("a");
|
||||
a?.addEventListener("click", async (e) => {
|
||||
e.preventDefault();
|
||||
if (new URL(a.href).host !== window.location.host) {
|
||||
console.log("innerHTML after replace", contentElement.innerHTML)
|
||||
const a = contentElement.querySelectorAll('a');
|
||||
a.forEach(el => el.addEventListener("click", (e) => {
|
||||
if (new URL(el.href).host !== $page.url.host) {
|
||||
e.preventDefault();
|
||||
externalLink = new URL(link);
|
||||
clickingExternalLink = true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -149,7 +159,7 @@
|
||||
{/if}
|
||||
|
||||
{#if clickingExternalLink}
|
||||
<AlertDialog.Root>
|
||||
<AlertDialog.Root open={clickingExternalLink}>
|
||||
<AlertDialog.Content>
|
||||
<AlertDialog.Header>
|
||||
<AlertDialog.Title class="mb-2 text-2xl font-bold"
|
||||
@ -157,11 +167,19 @@
|
||||
>
|
||||
<AlertDialog.Description>
|
||||
This link leads to a external website.
|
||||
Are you sure you want to open it?
|
||||
</AlertDialog.Description>
|
||||
</AlertDialog.Header>
|
||||
<AlertDialog.Footer>
|
||||
<AlertDialog.Action on:click={() => openExternalLink = true}>Open</AlertDialog.Action>
|
||||
<AlertDialog.Action on:click={() => openExternalLink = false}>Return to Lyntr</AlertDialog.Action>
|
||||
<AlertDialog.Action on:click={() => {
|
||||
if (!externalLink)
|
||||
return console.error("externalLink is null");
|
||||
window.open(externalLink)
|
||||
externalLink = null
|
||||
}}>Open</AlertDialog.Action>
|
||||
<AlertDialog.Action class="bg-primary" on:click={() => {
|
||||
clickingExternalLink = false
|
||||
}}>Return to Lyntr</AlertDialog.Action>
|
||||
</AlertDialog.Footer>
|
||||
</AlertDialog.Content>
|
||||
</AlertDialog.Root>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user