From 63dd0b2923d02a9da1f1b3dbd98256ea29811354 Mon Sep 17 00:00:00 2001 From: vaishnavi192 Date: Fri, 14 Aug 2026 16:51:14 +0530 Subject: [PATCH] fix: remove DOM dependency from ArticleCard Fixes: #683 Signed-off-by: vaishnavi192 --- src/components/ui/ArticleCard/index.tsx | 32 +++++++++++-------------- src/utils/htmlToText.ts | 26 ++++++++++++++++++++ 2 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 src/utils/htmlToText.ts diff --git a/src/components/ui/ArticleCard/index.tsx b/src/components/ui/ArticleCard/index.tsx index d1ff58c057..ef95e09de4 100644 --- a/src/components/ui/ArticleCard/index.tsx +++ b/src/components/ui/ArticleCard/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import parse from 'html-react-parser'; +import htmlToText from '@site/src/utils/htmlToText'; type ArticleCardProps = { title: string; subtitle: string; @@ -27,22 +27,18 @@ const PublishDate = ({ date, styles }: { date: string; styles?: string }) => { ); }; -const Title = (title: string) => { - return

{title}

; -}; - function ArticleCard(props: ArticleCardProps) { // Select fallback image based on index, cycling through available images const fallbackImage = FALLBACK_IMAGES[(props.index || 0) % FALLBACK_IMAGES.length]; - - // Sanitizes HTML and converts it to plain text - const sanitizeHtml = (html: string) => { - if (!html) return html; - const div = document.createElement("div"); - div.innerHTML = html; - return div.textContent || div.innerText || ""; + const subtitleStyle: React.CSSProperties = { + display: '-webkit-box', + WebkitBoxOrient: 'vertical', + WebkitLineClamp: 3, + overflow: 'hidden', }; - const abbrSubtitle = sanitizeHtml(props.subtitle).trim().split(' ').slice(0, 32).join(' ').concat('...'); + + const titleContent = htmlToText(props.title); + const subtitleContent = htmlToText(props.subtitle); if (props.altLayout) { return (
@@ -54,7 +50,7 @@ function ArticleCard(props: ArticleCardProps) { href={props.path} target="_blank" className="text-white no-underline hover:text-blue-100 hover:no-underline dark:text-white dark:hover:text-blue-50"> - {sanitizeHtml(props.title)} + {titleContent} @@ -64,8 +60,8 @@ function ArticleCard(props: ArticleCardProps) { className=" col-start-1 row-start-1 h-full w-full rounded-sm object-cover lg:w-80" /> -
- {parse(abbrSubtitle)} +
+ {subtitleContent}

By: {props.display_name}

@@ -84,10 +80,10 @@ function ArticleCard(props: ArticleCardProps) { href={props.path} target="_blank" className="text-white no-underline hover:text-blue-100 hover:no-underline dark:text-white dark:hover:text-blue-50"> - {sanitizeHtml(props.title)} + {titleContent} - {parse(abbrSubtitle)} +
{subtitleContent}

diff --git a/src/utils/htmlToText.ts b/src/utils/htmlToText.ts new file mode 100644 index 0000000000..580f21b4e0 --- /dev/null +++ b/src/utils/htmlToText.ts @@ -0,0 +1,26 @@ +import React from 'react'; +import parse from 'html-react-parser'; + +const collectText = (node: React.ReactNode): string => { + if (typeof node === 'string' || typeof node === 'number') { + return String(node); + } + + if (Array.isArray(node)) { + return node.map(collectText).join(''); + } + + if (React.isValidElement(node)) { + return collectText(node.props.children); + } + + return ''; +}; + +export default function htmlToText(html: string): string { + if (!html) { + return ''; + } + + return collectText(parse(html)); +} \ No newline at end of file