Compare commits

...

2 Commits

Author SHA1 Message Date
06b8c8fa0b BLOG-45 fix: XSS html issue
All checks were successful
Frontend CI / build (push) Successful in 1m3s
2025-07-24 12:29:14 +08:00
e4807cac7a BLOG-45 refactor: format 2025-07-24 12:19:06 +08:00
7 changed files with 33 additions and 5 deletions

View File

@ -24,6 +24,7 @@
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.0.0",
"@types/markdown-it": "^14.1.2",
"dompurify": "^3.2.6",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^3.0.0",

View File

@ -38,6 +38,9 @@ importers:
'@types/markdown-it':
specifier: ^14.1.2
version: 14.1.2
dompurify:
specifier: ^3.2.6
version: 3.2.6
eslint:
specifier: ^9.18.0
version: 9.31.0(jiti@2.4.2)
@ -640,6 +643,9 @@ packages:
'@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
'@typescript-eslint/eslint-plugin@8.38.0':
resolution: {integrity: sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -809,6 +815,9 @@ packages:
devalue@5.1.1:
resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
dompurify@3.2.6:
resolution: {integrity: sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==}
enhanced-resolve@5.18.2:
resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==}
engines: {node: '>=10.13.0'}
@ -1997,6 +2006,9 @@ snapshots:
'@types/resolve@1.20.2': {}
'@types/trusted-types@2.0.7':
optional: true
'@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)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@ -2175,6 +2187,10 @@ snapshots:
devalue@5.1.1: {}
dompurify@3.2.6:
optionalDependencies:
'@types/trusted-types': 2.0.7
enhanced-resolve@5.18.2:
dependencies:
graceful-fs: 4.2.11

View File

@ -0,0 +1,11 @@
<script lang="ts">
/* eslint-disable svelte/no-at-html-tags */
import DOMPurify from 'dompurify';
const { html }: { html: string } = $props();
const sanitizedHtml = $derived(DOMPurify.sanitize(html));
</script>
{@html sanitizedHtml}

View File

@ -3,6 +3,7 @@
import PostContentHeader from '$lib/post/framework/ui/PostContentHeader.svelte';
import { getContext, onMount } from 'svelte';
import markdownit from 'markdown-it';
import SafeHtml from '$lib/common/framework/ui/SafeHtml.svelte';
const { id }: { id: number } = $props();
@ -15,12 +16,12 @@
onMount(() => postBloc.dispatch({ event: PostEventType.PostLoadedEvent, id: id }));
</script>
<article class="prose container pb-10">
<article class="container prose pb-10">
{#if state.data}
<PostContentHeader postInfo={state.data.info} />
<div class="max-w-3xl">
<hr />
{@html parsedContent}
<SafeHtml html={parsedContent} />
</div>
{/if}
</article>

View File

@ -1,5 +1,4 @@
<script lang="ts">
import { StatusType } from '$lib/common/adapter/presenter/asyncState';
import { PostListBloc, PostListEventType } from '$lib/post/adapter/presenter/postListBloc';
import PostPreview from '$lib/post/framework/ui/PostPreview.svelte';
import { getContext, onMount } from 'svelte';

View File

@ -34,7 +34,7 @@
</div>
<div class="flex flex-col gap-y-2.5">
<PostPreviewLabels labels={postInfo.labels} />
<span class="line-clamp-1 font-bold text-lg">{postInfo.title}</span>
<span class="line-clamp-1 text-lg font-bold">{postInfo.title}</span>
<span class="line-clamp-3 text-justify text-sm">{postInfo.description}</span>
<span class="text-sm text-gray-500">{postInfo.formattedPublishedTime}</span>
</div>

View File

@ -3,7 +3,7 @@
</script>
<div
class="min-h-content-height mx-auto flex max-w-screen-xl flex-col items-center justify-center px-4 md:px-6"
class="mx-auto flex min-h-content-height max-w-screen-xl flex-col items-center justify-center px-4 md:px-6"
>
<div class="flex flex-row items-end gap-x-4 md:gap-x-6">
<h1 class="text-5xl font-extrabold text-gray-800 underline md:text-7xl">404</h1>