Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions web/src/lib/components/PostCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -93,46 +93,47 @@
}
</script>

<article
<a
href="/post/{post.id}"
data-nav-item
data-nav-id={post.id}
class="bg-card rounded-xl py-3 pl-3 pr-3 sm:pl-4 border border-border hover:border-border-hover transition-colors duration-200 w-full sm:w-fit"
data-nav-link
class="block bg-card rounded-xl py-3 pl-3 pr-3 sm:pl-4 border border-border hover:border-border-hover transition-colors duration-200 w-full sm:w-fit"
>
<div class="flex flex-col gap-2">
<article class="flex flex-col gap-2">
<div>
<a
href="/site/{post.domain}"
<button
type="button"
onclick={(e) => { e.preventDefault(); e.stopPropagation(); goto(`/site/${post.domain}`); }}
class="float-right ml-2 mb-0 sm:mb-1 text-xs border-input border text-muted-foreground hover:border-border-hover hover:text-foreground transition-colors duration-200 px-2 py-0.5 sm:py-1 rounded-full max-w-[40%] truncate"
>
{post.domain}
</a>
<a
href={post.url}
target="_blank"
rel="noopener noreferrer"
data-nav-link
class="hover:underline text-foreground hover:text-muted-foreground text-sm leading-snug break-words sm:max-w-2xl"
>
</button>
<span class="hover:underline text-foreground hover:text-muted-foreground text-sm leading-snug break-words sm:max-w-2xl">
{post.title}
</a>
</span>
</div>
<div class="flex items-center gap-2 sm:gap-3 text-xs text-muted-foreground flex-wrap">
<UpvoteButton
count={optimisticCount}
active={optimisticUpvoted}
onclick={handleUpvote}
onclick={(e) => { e.preventDefault(); e.stopPropagation(); handleUpvote(); }}
{loading}
/>
<span class="hidden sm:inline">·</span>
<span>{getRelativeTime(post.createdAt)}</span>
<span>·</span>
<a href="/user/{post.author.username}" class="hover:text-foreground truncate max-w-[100px] sm:max-w-none">
<button
type="button"
onclick={(e) => { e.preventDefault(); e.stopPropagation(); goto(`/user/${post.author.username}`); }}
class="hover:text-foreground truncate max-w-[100px] sm:max-w-none"
>
{post.author.username}
</a>
</button>
<span>·</span>
<a href="/post/{post.id}" data-nav-comments class="hover:text-foreground">
<span data-nav-comments class="hover:text-foreground">
comentarios
</a>
</span>
</div>
</div>
</article>
</article>
</a>
39 changes: 22 additions & 17 deletions web/src/lib/components/PostHeader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -87,37 +87,42 @@
}
</script>

<article class="bg-card border border-border rounded-xl p-4">
<div class="flex justify-between items-start gap-2">
<a
href={post.url}
target="_blank"
rel="noopener noreferrer"
class="block bg-card border border-border hover:border-border-hover transition-colors duration-200 rounded-xl p-4"
>
<article class="flex justify-between items-start gap-2">
<div>
<a
href={post.url}
target="_blank"
rel="noopener noreferrer"
class="text-lg text-foreground hover:underline"
>
<span class="text-lg text-foreground hover:underline">
{post.title}
</a>
</span>
<div class="flex items-center gap-2 text-xs text-muted-foreground mt-4">
<UpvoteButton
count={optimisticCount}
active={optimisticUpvoted}
onclick={handleUpvote}
onclick={(e) => { e.preventDefault(); e.stopPropagation(); handleUpvote(); }}
{loading}
/>
<span>·</span>
<span>{getRelativeTime(post.createdAt)}</span>
<span>·</span>
<a href="/user/{post.author.username}" class="hover:text-foreground">
<button
type="button"
onclick={(e) => { e.preventDefault(); e.stopPropagation(); goto(`/user/${post.author.username}`); }}
class="hover:text-foreground"
>
{post.author.username}
</a>
</button>
</div>
</div>
<a
href="/site/{post.domain}"
<button
type="button"
onclick={(e) => { e.preventDefault(); e.stopPropagation(); goto(`/site/${post.domain}`); }}
class="text-xs shrink-0 border-input border text-muted-foreground hover:border-border-hover hover:text-foreground transition-colors duration-200 px-2 py-1 rounded-full max-w-[120px] truncate"
>
{post.domain}
</a>
</div>
</article>
</button>
</article>
</a>
2 changes: 1 addition & 1 deletion web/src/lib/components/UpvoteButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
}: {
count?: number;
active?: boolean;
onclick?: () => void;
onclick?: (e: MouseEvent) => void;
disabled?: boolean;
loading?: boolean;
} = $props();
Expand Down
13 changes: 2 additions & 11 deletions web/src/routes/og/post/[id]/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,12 @@ export const GET: RequestHandler = async ({ params }) => {
<img src="${logoBase64}" width="50" height="50" />
<span style="margin-left: 16px; font-size: 32px; font-weight: 600; color: #141414;">the stack</span>
</div>
<span style="font-size: 48px; font-weight: 700; color: #141414; text-align: center;">${escapeHtml(title)}</span>
<span style="font-size: 24px; color: #666666; text-align: center;">${escapeHtml(subtitle)}</span>
<span style="font-size: 48px; font-weight: 700; color: #141414; text-align: center;">${title}</span>
<span style="font-size: 24px; color: #666666; text-align: center;">${subtitle}</span>
</div>`;

return new ImageResponse(html, {
width: 1200,
height: 630
});
};

function escapeHtml(str: string): string {
return str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}