Skip to content

Instantly share code, notes, and snippets.

@SerJaimeLannister
Last active January 3, 2025 15:20
Show Gist options
  • Select an option

  • Save SerJaimeLannister/171fbb52653b83c1cff1d0e265115a28 to your computer and use it in GitHub Desktop.

Select an option

Save SerJaimeLannister/171fbb52653b83c1cff1d0e265115a28 to your computer and use it in GitHub Desktop.
Haven't decided the license yet so probably don't use it right away in your project ?
Maybe I am thinking of creating a fork since creating the core functionality was rather trivial.
<script lang="ts">
import { onMount } from 'svelte';
import Highlight from 'svelte-highlight';
import { d } from 'svelte-highlight/languages';
import javascript from 'svelte-highlight/languages/javascript';
import github from 'svelte-highlight/styles/github';
import githubDark from 'svelte-highlight/styles/github-dark';
interface Comment {
creator: string;
content: string;
published: string;
}
interface ParsedPost {
id: number;
metadata: {
title: string;
description: string;
author: string;
tags: string;
};
mainCode: string;
usage: string;
language: string;
comments: Comment[];
}
export let darkMode = false;
let posts: ParsedPost[] = [];
async function fetchComments(postId: number): Promise<Comment[]> {
const response = await fetch(
`https://discuss.online/api/v3/comment/list?post_id=${postId}`
);
const data = await response.json();
return data.comments.map((comment) => ({
creator: comment.creator.name,
content: comment.comment.content,
published: new Date(comment.comment.published).toLocaleString()
}));
}
function parsePostContent(post: any): ParsedPost | null {
try {
const parts = post.body.split('---').filter(Boolean);
if (parts.length < 2) return null;
const metadata = {};
parts[0].split('\n').forEach((line) => {
const [key, ...valueParts] = line.split(':');
const value = valueParts.join(':').trim();
if (key && value) metadata[key.trim()] = value;
});
const codeMatch = parts[1].match(/```(\w+)?\n([\s\S]*?)```/);
const language = (codeMatch?.[1] || 'javascript').toLowerCase();
const code = codeMatch?.[2].trim() || '';
const usageMatch = code.match(/(\/\/ Usage:[\s\S]*$)/);
const mainCode = code.replace(usageMatch?.[0] || '', '').trim();
const usage = usageMatch?.[1] || '';
return {
id: post.id,
metadata,
mainCode,
usage,
language,
comments: []
};
} catch (error) {
console.error('Error parsing post:', error);
return null;
}
}
onMount(async () => {
try {
const response = await fetch(
'https://discuss.online/api/v3/post/list?community_name=Quicksnip'
);
const data = await response.json();
posts = await Promise.all(
data.posts
.map((item) => parsePostContent(item.post))
.filter((post) => post !== null)
.map(async (post) => {
post.comments = await fetchComments(post.id);
return post;
})
);
} catch (error) {
console.error('Error fetching data:', error);
}
});
</script>
<svelte:head>
{@html darkMode ? githubDark : github}
</svelte:head>
<div class="min-h-screen {darkMode ? 'bg-gray-900 text-white' : 'bg-white text-gray-900'}">
<div class="container mx-auto p-4">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold">Posts</h1>
<button
on:click={() => (darkMode = !darkMode)}
class="p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700"
>
{#if darkMode}
☀️
{:else}
🌙
{/if}
</button>
</div>
</div>
<div class="grid gap-6">
{#each posts as post}
<div class="rounded-lg shadow-lg {darkMode ? 'bg-gray-800' : 'bg-white'} p-6">
<div class="grid md:grid-cols-2 gap-4 mb-6">
<div>
<h2 class="text-2xl font-bold mb-2">{post.metadata.title || 'Untitled'}</h2>
<p class="text-gray-600 dark:text-gray-300 mb-4">
{post.metadata.description || 'No description'}
</p>
{#if post.metadata.tags}
<div class="flex flex-wrap gap-2 mb-4">
{#each post.metadata.tags.split(',') as tag}
<span
class="px-2 py-1 bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-100 rounded-full text-sm"
>
{tag.trim()}
</span>
{/each}
</div>
{/if}
{#if post.metadata.author}
<p class="text-sm text-gray-500 dark:text-gray-400">
By {post.metadata.author}
</p>
{/if}
</div>
<div class="space-y-4">
{#if post.mainCode}
<div class="rounded-lg overflow-hidden">
<Highlight language={javascript} code={post.mainCode} />
</div>
{/if}
{#if post.usage}
<div class="rounded-lg overflow-hidden">
<div
class="bg-gray-100 dark:bg-gray-700 px-4 py-2 text-sm font-semibold"
>
Usage Example
</div>
<Highlight language={javascript} code={post.usage} />
</div>
{/if}
</div>
</div>
{#if post.comments.length > 0}
<div class="border-t border-gray-200 dark:border-gray-700 pt-4 mt-4">
<h3 class="text-lg font-semibold mb-4">Comments</h3>
<div class="space-y-4">
{#each post.comments as comment}
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
<div class="flex justify-between mb-2">
<span class="font-medium text-blue-600 dark:text-blue-400"
>{comment.creator}</span
>
<span class="text-sm text-gray-500 dark:text-gray-400"
>{comment.published}</span
>
</div>
<p class="text-gray-700 dark:text-gray-300">
{comment.content}
</p>
</div>
{/each}
</div>
</div>
{/if}
</div>
{/each}
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment