From b19d453682a241ac06912274409213c0b5b8412c Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 2 Mar 2025 17:12:46 -0600 Subject: [PATCH] feat: enhance markdown rendering with GFM plugins and image handling --- .../blog/[slug]/components/ZoomableImage.tsx | 10 +--- .../website/app/[locale]/blog/[slug]/page.tsx | 49 ++++++------------ apps/website/package.json | 6 ++- package.json | 6 --- pnpm-lock.yaml | 50 +++++++------------ 5 files changed, 40 insertions(+), 81 deletions(-) diff --git a/apps/website/app/[locale]/blog/[slug]/components/ZoomableImage.tsx b/apps/website/app/[locale]/blog/[slug]/components/ZoomableImage.tsx index dd0c276..702c342 100644 --- a/apps/website/app/[locale]/blog/[slug]/components/ZoomableImage.tsx +++ b/apps/website/app/[locale]/blog/[slug]/components/ZoomableImage.tsx @@ -1,9 +1,8 @@ "use client"; -import Image from "next/image"; +import { cn } from "@/lib/utils"; import { PhotoProvider, PhotoView } from "react-photo-view"; import "react-photo-view/dist/react-photo-view.css"; - interface ZoomableImageProps { src: string; alt: string; @@ -14,12 +13,7 @@ export function ZoomableImage({ src, alt, className }: ZoomableImageProps) { return ( - {alt} + {alt} ); diff --git a/apps/website/app/[locale]/blog/[slug]/page.tsx b/apps/website/app/[locale]/blog/[slug]/page.tsx index 32af490..958431b 100644 --- a/apps/website/app/[locale]/blog/[slug]/page.tsx +++ b/apps/website/app/[locale]/blog/[slug]/page.tsx @@ -14,7 +14,10 @@ import remarkGfm from "remark-gfm"; import { codeToHtml } from "shiki"; import type { BundledLanguage } from "shiki/bundle/web"; import TurndownService from "turndown"; +// @ts-ignore +import * as turndownPluginGfm from "turndown-plugin-gfm"; import { ZoomableImage } from "./components/ZoomableImage"; + type Props = { params: { locale: string; slug: string }; }; @@ -128,39 +131,13 @@ export default async function BlogPostPage({ params }: Props) { headingStyle: "atx", codeBlockStyle: "fenced", }); - - // Configurar el manejo de tablas - turndownService.addRule("table", { - filter: ["table"], - replacement: (content, node) => { - const rows = node.rows; - let markdown = "\n"; - - // Headers - if (rows.length > 0) { - const headers = Array.from(rows[0].cells).map((cell) => - cell.textContent.trim(), - ); - markdown += `| ${headers.join(" | ")} |\n`; - markdown += `| ${headers.map(() => "---").join(" | ")} |\n`; - } - - // Body - for (let i = 1; i < rows.length; i++) { - const cells = Array.from(rows[i].cells).map((cell) => - cell.textContent.trim(), - ); - markdown += `| ${cells.join(" | ")} |\n`; - } - - return `${markdown}\n`; - }, - }); + const gfm = turndownPluginGfm.gfm; + const tables = turndownPluginGfm.tables; + const strikethrough = turndownPluginGfm.strikethrough; + turndownService.use([tables, strikethrough, gfm]); const markdown = turndownService.turndown(post.html); - console.log(markdown); - const formattedDate = new Date(post.published_at).toLocaleDateString(locale, { year: "numeric", month: "long", @@ -232,9 +209,11 @@ export default async function BlogPostPage({ params }: Props) { ), img: ({ node, src, alt }) => ( - - {src && } - + ), code: ({ inline, className, children, ...props }: CodeProps) => { const match = /language-(\w+)/.exec(className || ""); @@ -319,11 +298,11 @@ export default async function BlogPostPage({ params }: Props) { {post.feature_image && ( -
+
)} diff --git a/apps/website/package.json b/apps/website/package.json index dc118f1..ef3d913 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -43,7 +43,11 @@ "tailwindcss": "^3.4.1", "tailwindcss-animate": "^1.0.7", "turndown": "^7.2.0", - "typescript": "5.1.6" + "turndown-plugin-gfm": "^1.0.2", + "typescript": "5.1.6", + "react-markdown": "^10.0.0", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/package.json b/package.json index dd83963..b1400fb 100644 --- a/package.json +++ b/package.json @@ -41,11 +41,5 @@ "resolutions": { "@types/react": "18.3.5", "@types/react-dom": "18.3.0" - }, - "dependencies": { - "prism-react-renderer": "^2.4.1", - "react-markdown": "^10.0.0", - "rehype-raw": "^7.0.0", - "remark-gfm": "^4.0.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d771ab9..b0945c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,19 +11,6 @@ overrides: importers: .: - dependencies: - prism-react-renderer: - specifier: ^2.4.1 - version: 2.4.1(react@18.3.1) - react-markdown: - specifier: ^10.0.0 - version: 10.0.0(@types/react@18.3.5)(react@18.3.1) - rehype-raw: - specifier: ^7.0.0 - version: 7.0.0 - remark-gfm: - specifier: ^4.0.1 - version: 4.0.1 devDependencies: '@biomejs/biome': specifier: 1.8.3 @@ -179,9 +166,18 @@ importers: react-ga4: specifier: ^2.1.0 version: 2.1.0 + react-markdown: + specifier: ^10.0.0 + version: 10.0.0(@types/react@18.3.5)(react@18.2.0) react-photo-view: specifier: ^1.2.7 version: 1.2.7(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + rehype-raw: + specifier: ^7.0.0 + version: 7.0.0 + remark-gfm: + specifier: ^4.0.1 + version: 4.0.1 shiki: specifier: 1.22.2 version: 1.22.2 @@ -197,6 +193,9 @@ importers: turndown: specifier: ^7.2.0 version: 7.2.0 + turndown-plugin-gfm: + specifier: ^1.0.2 + version: 1.0.2 typescript: specifier: 5.1.6 version: 5.1.6 @@ -1660,9 +1659,6 @@ packages: '@types/node@22.9.0': resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==} - '@types/prismjs@1.26.5': - resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} - '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -3127,11 +3123,6 @@ packages: engines: {node: '>=14'} hasBin: true - prism-react-renderer@2.4.1: - resolution: {integrity: sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==} - peerDependencies: - react: '>=16.0.0' - property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -3532,6 +3523,9 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + turndown-plugin-gfm@1.0.2: + resolution: {integrity: sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==} + turndown@7.2.0: resolution: {integrity: sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==} @@ -5286,8 +5280,6 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/prismjs@1.26.5': {} - '@types/prop-types@15.7.12': {} '@types/react-dom@18.3.0': @@ -7068,12 +7060,6 @@ snapshots: prettier@3.3.3: {} - prism-react-renderer@2.4.1(react@18.3.1): - dependencies: - '@types/prismjs': 1.26.5 - clsx: 2.1.1 - react: 18.3.1 - property-information@6.5.0: {} property-information@7.0.0: {} @@ -7104,7 +7090,7 @@ snapshots: dependencies: react: 18.3.1 - react-markdown@10.0.0(@types/react@18.3.5)(react@18.3.1): + react-markdown@10.0.0(@types/react@18.3.5)(react@18.2.0): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 @@ -7113,7 +7099,7 @@ snapshots: hast-util-to-jsx-runtime: 2.3.2 html-url-attributes: 3.0.1 mdast-util-to-hast: 13.2.0 - react: 18.3.1 + react: 18.2.0 remark-parse: 11.0.0 remark-rehype: 11.1.1 unified: 11.0.5 @@ -7598,6 +7584,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + turndown-plugin-gfm@1.0.2: {} + turndown@7.2.0: dependencies: '@mixmark-io/domino': 2.2.0