feat: support Markdown rendering in product details
This commit is contained in:
1 parent
ef89731c86
commit
730e2a7b48
2 files changed
+11
-2
No files matched your search
@@ -12,8 +12,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@homaroma/types": "workspace:*",
|
"@homaroma/types": "workspace:*",
|
||||||
"@line/liff": "^2.28.0",
|
"@line/liff": "^2.28.0",
|
||||||
|
"dompurify": "^3.4.10",
|
||||||
"i18next": "^26.0.4",
|
"i18next": "^26.0.4",
|
||||||
"lucide-react": "^1.17.0",
|
"lucide-react": "^1.17.0",
|
||||||
|
"marked": "^18.0.5",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
"react-i18next": "^17.0.2",
|
"react-i18next": "^17.0.2",
|
||||||
@@ -24,6 +26,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.4",
|
"@eslint/js": "^9.39.4",
|
||||||
"@tailwindcss/postcss": "^4.2.2",
|
"@tailwindcss/postcss": "^4.2.2",
|
||||||
|
"@types/dompurify": "^3.2.0",
|
||||||
"@types/node": "^24.12.0",
|
"@types/node": "^24.12.0",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import ProductImageGallery from '../components/ProductImageGallery'
|
|||||||
import DynamicPageRenderer from '../components/DynamicPageRenderer'
|
import DynamicPageRenderer from '../components/DynamicPageRenderer'
|
||||||
import { API_BASE, getCategoryImage, formatPrice, type Category, type Product, type PageSection, type TranslatableString } from '../types'
|
import { API_BASE, getCategoryImage, formatPrice, type Category, type Product, type PageSection, type TranslatableString } from '../types'
|
||||||
import { useCartStore } from '../store/cartStore'
|
import { useCartStore } from '../store/cartStore'
|
||||||
|
import { marked } from 'marked'
|
||||||
|
import DOMPurify from 'dompurify'
|
||||||
|
|
||||||
/** แปลง TranslatableString (string | Record<string,string>) เป็น string ตาม locale */
|
/** แปลง TranslatableString (string | Record<string,string>) เป็น string ตาม locale */
|
||||||
function resolveTranslatable(value: TranslatableString | null | undefined, lang: string): string {
|
function resolveTranslatable(value: TranslatableString | null | undefined, lang: string): string {
|
||||||
@@ -270,8 +272,12 @@ export default function ProductDetailPage() {
|
|||||||
<div className="pt-16 border-t border-spa-stone/10 space-y-6">
|
<div className="pt-16 border-t border-spa-stone/10 space-y-6">
|
||||||
<h2 className="text-3xl font-bold text-pop-black">{t('product.details')}</h2>
|
<h2 className="text-3xl font-bold text-pop-black">{t('product.details')}</h2>
|
||||||
<div
|
<div
|
||||||
className="prose prose-spa prose-lg max-w-4xl product-editorial text-spa-stone"
|
className="prose prose-spa prose-lg max-w-4xl product-editorial text-spa-stone whitespace-pre-wrap"
|
||||||
dangerouslySetInnerHTML={{ __html: resolveTranslatable(product.details, i18n.language) }}
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: DOMPurify.sanitize(
|
||||||
|
marked.parse(resolveTranslatable(product.details, i18n.language).replace(/\\n/g, '\n'), { async: false }) as string
|
||||||
|
)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in new issue
Block a user