From f07460d95ce041ec7c0636b85cd0402b01e36a1c Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Thu, 24 Jul 2025 12:13:41 +0800 Subject: [PATCH] BLOG-45 feat: add markdown-it and types for improved post content rendering --- frontend/package.json | 2 + frontend/pnpm-lock.yaml | 66 +++++++++++++++++++ frontend/src/app.css | 10 +-- .../framework/ui/PostContentHeader.svelte | 6 +- .../post/framework/ui/PostContentPage.svelte | 12 +++- .../lib/post/framework/ui/PostPreview.svelte | 4 +- 6 files changed, 85 insertions(+), 15 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 84a9605..91031de 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,10 +23,12 @@ "@sveltejs/vite-plugin-svelte": "^6.0.0", "@tailwindcss/typography": "^0.5.15", "@tailwindcss/vite": "^4.0.0", + "@types/markdown-it": "^14.1.2", "eslint": "^9.18.0", "eslint-config-prettier": "^10.0.1", "eslint-plugin-svelte": "^3.0.0", "globals": "^16.0.0", + "markdown-it": "^14.1.0", "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.3", "prettier-plugin-tailwindcss": "^0.6.11", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 519b4f5..9dce47f 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: '@tailwindcss/vite': specifier: ^4.0.0 version: 4.1.11(vite@7.0.5(jiti@2.4.2)(lightningcss@1.30.1)) + '@types/markdown-it': + specifier: ^14.1.2 + version: 14.1.2 eslint: specifier: ^9.18.0 version: 9.31.0(jiti@2.4.2) @@ -47,6 +50,9 @@ importers: globals: specifier: ^16.0.0 version: 16.3.0 + markdown-it: + specifier: ^14.1.0 + version: 14.1.0 prettier: specifier: ^3.4.2 version: 3.6.2 @@ -622,6 +628,15 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -798,6 +813,10 @@ packages: resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==} engines: {node: '>=10.13.0'} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + esbuild@0.25.8: resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==} engines: {node: '>=18'} @@ -1098,6 +1117,9 @@ packages: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} @@ -1117,6 +1139,13 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true + + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1314,6 +1343,10 @@ packages: engines: {node: '>=14'} hasBin: true + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1452,6 +1485,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1950,6 +1986,15 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/linkify-it@5.0.0': {} + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/mdurl@2.0.0': {} + '@types/resolve@1.20.2': {} '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3)': @@ -2135,6 +2180,8 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.2 + entities@4.5.0: {} + esbuild@0.25.8: optionalDependencies: '@esbuild/aix-ppc64': 0.25.8 @@ -2441,6 +2488,10 @@ snapshots: lilconfig@2.1.0: {} + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + locate-character@3.0.0: {} locate-path@6.0.0: @@ -2457,6 +2508,17 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.4 + markdown-it@14.1.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + mdurl@2.0.0: {} + merge2@1.4.1: {} micromatch@4.0.8: @@ -2569,6 +2631,8 @@ snapshots: prettier@3.6.2: {} + punycode.js@2.3.1: {} + punycode@2.3.1: {} queue-microtask@1.2.3: {} @@ -2730,6 +2794,8 @@ snapshots: typescript@5.8.3: {} + uc.micro@2.1.0: {} + uri-js@4.4.1: dependencies: punycode: 2.3.1 diff --git a/frontend/src/app.css b/frontend/src/app.css index e489be2..224a8cb 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,4 +1,5 @@ @import 'tailwindcss'; +@plugin '@tailwindcss/typography'; @font-face { font-family: 'HackNerdMono'; @@ -25,14 +26,7 @@ } body { - @apply bg-white font-sans text-base font-normal text-gray-800; -} - -pre, -code, -kbd, -samp { - @apply font-mono; + @apply bg-white font-sans text-base font-normal text-gray-700; } .container { diff --git a/frontend/src/lib/post/framework/ui/PostContentHeader.svelte b/frontend/src/lib/post/framework/ui/PostContentHeader.svelte index 5f5d503..c4dcae9 100644 --- a/frontend/src/lib/post/framework/ui/PostContentHeader.svelte +++ b/frontend/src/lib/post/framework/ui/PostContentHeader.svelte @@ -5,13 +5,13 @@ const { postInfo }: { postInfo: PostInfoViewModel } = $props(); -
+
{#each postInfo.labels as label (label.id)}
-

{postInfo.title}

- {postInfo.description} +

{postInfo.title}

+

{postInfo.description}

{postInfo.formattedPublishedTime}
diff --git a/frontend/src/lib/post/framework/ui/PostContentPage.svelte b/frontend/src/lib/post/framework/ui/PostContentPage.svelte index 1c94d80..a19d596 100644 --- a/frontend/src/lib/post/framework/ui/PostContentPage.svelte +++ b/frontend/src/lib/post/framework/ui/PostContentPage.svelte @@ -2,17 +2,25 @@ import { PostBloc, PostEventType } from '$lib/post/adapter/presenter/postBloc'; import PostContentHeader from '$lib/post/framework/ui/PostContentHeader.svelte'; import { getContext, onMount } from 'svelte'; + import markdownit from 'markdown-it'; const { id }: { id: number } = $props(); const postBloc = getContext(PostBloc.name); const state = $derived($postBloc); + const md = markdownit(); + const parsedContent = $derived(state.data?.content ? md.render(state.data.content) : ''); + onMount(() => postBloc.dispatch({ event: PostEventType.PostLoadedEvent, id: id })); -
+
{#if state.data} +
+
+ {@html parsedContent} +
{/if} -
+ diff --git a/frontend/src/lib/post/framework/ui/PostPreview.svelte b/frontend/src/lib/post/framework/ui/PostPreview.svelte index 189c375..2aef09b 100644 --- a/frontend/src/lib/post/framework/ui/PostPreview.svelte +++ b/frontend/src/lib/post/framework/ui/PostPreview.svelte @@ -17,7 +17,7 @@ } - +
{/if}
-
+
{postInfo.title} {postInfo.description}