Last active
January 3, 2025 15:20
-
-
Save SerJaimeLannister/171fbb52653b83c1cff1d0e265115a28 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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