From bf22377b0704e0d03b3c5d9f79c448d0451665de Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 08:26:18 +0200 Subject: [PATCH 01/11] feat: improve off-chain proposal HTML support - Updated tooltip text from "Allow markup" to "Allow HTML" for better clarity - Increased description character limit from 1,500 to 10,000 characters - Applies to both community creation and proposal creation forms This improves the user experience when creating off-chain proposals with HTML-formatted descriptions. --- src/modules/lite/creator/index.tsx | 4 ++-- src/modules/lite/explorer/pages/CreateProposal/index.tsx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/lite/creator/index.tsx b/src/modules/lite/creator/index.tsx index 01225acc..b2cb7ef9 100644 --- a/src/modules/lite/creator/index.tsx +++ b/src/modules/lite/creator/index.tsx @@ -298,13 +298,13 @@ const CommunityForm = ({ submitForm, values, setFieldValue, errors, touched, set {!isMarkup ? (
- + setIsMarkup(true)} />
) : (
- + setIsMarkup(false)} />
diff --git a/src/modules/lite/explorer/pages/CreateProposal/index.tsx b/src/modules/lite/explorer/pages/CreateProposal/index.tsx index 3a7298d6..31032c32 100644 --- a/src/modules/lite/explorer/pages/CreateProposal/index.tsx +++ b/src/modules/lite/explorer/pages/CreateProposal/index.tsx @@ -529,13 +529,13 @@ export const ProposalForm = ({ {!isMarkup ? (
- + setIsMarkup(true)} />
) : (
- + setIsMarkup(false)} />
@@ -544,7 +544,7 @@ export const ProposalForm = ({ {() => ( Date: Fri, 14 Nov 2025 08:40:49 +0200 Subject: [PATCH 02/11] fix: replace deprecated react-html-parser with html-react-parser - Upgraded from react-html-parser (last updated 2017) to html-react-parser (actively maintained, React 18 compatible) - Fixes HTML rendering issues in production builds - Removed whiteSpace: "pre-line" style that was causing excessive spacing with HTML content - Updated all 6 files that use HTML parsing This fixes the issue where HTML descriptions weren't rendering correctly in production/deploy previews. --- package.json | 2 +- .../components/EvmProposalDetailCard.tsx | 4 +- .../pages/DAOList/components/DAOItem.tsx | 4 +- .../explorer/pages/ProposalDetails/index.tsx | 4 +- .../explorer/components/DaoCardDetail.tsx | 4 +- .../components/ProposalDetailCard.tsx | 5 +- .../explorer/components/ProposalTableRow.tsx | 4 +- yarn.lock | 72 +++++++++---------- 8 files changed, 49 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index 479ecfd5..73aa4c62 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "graphql": "^15.5.1", "graphql-request": "^3.4.0", "hex-to-rgba": "^2.0.1", - "html-react-parser": "^5.0.6", + "html-react-parser": "^5.2.8", "https-browserify": "^1.0.0", "jsonschema": "^1.4.0", "notistack": "^1.0.3", diff --git a/src/modules/etherlink/components/EvmProposalDetailCard.tsx b/src/modules/etherlink/components/EvmProposalDetailCard.tsx index 574e2559..ca9f5890 100644 --- a/src/modules/etherlink/components/EvmProposalDetailCard.tsx +++ b/src/modules/etherlink/components/EvmProposalDetailCard.tsx @@ -7,7 +7,7 @@ import Share from "assets/img/share.svg" import LinkIcon from "assets/img/link.svg" import { useNotification } from "modules/common/hooks/useNotification" -import ReactHtmlParser from "react-html-parser" +import parse from "html-react-parser" import { Badge } from "components/ui/Badge" import { StatusBadge } from "modules/explorer/components/StatusBadge" import { CopyIcon } from "components/ui/icons/CopyIcon" @@ -163,7 +163,7 @@ export const EvmProposalDetailCard: React.FC<{ poll: IEvmProposal | undefined; d - {ReactHtmlParser(daoProposalSelected?.description ? daoProposalSelected?.description : "")} + {parse(daoProposalSelected?.description ? daoProposalSelected?.description : "")} diff --git a/src/modules/explorer/pages/DAOList/components/DAOItem.tsx b/src/modules/explorer/pages/DAOList/components/DAOItem.tsx index f626e360..9cb6efea 100644 --- a/src/modules/explorer/pages/DAOList/components/DAOItem.tsx +++ b/src/modules/explorer/pages/DAOList/components/DAOItem.tsx @@ -1,7 +1,7 @@ import { styled, Grid, Theme, Typography, Link, useTheme, useMediaQuery } from "@material-ui/core" import React from "react" import { EnvKey, getEnv } from "services/config" -import ReactHtmlParser from "react-html-parser" +import parse from "html-react-parser" import { formatNumber } from "modules/explorer/utils/FormatNumber" import BigNumber from "bignumber.js" import { getDaoHref } from "utils" @@ -143,7 +143,7 @@ export const DAOItem: React.FC<{
- {ReactHtmlParser(dao.description)} + {parse(dao.description)} diff --git a/src/modules/explorer/pages/ProposalDetails/index.tsx b/src/modules/explorer/pages/ProposalDetails/index.tsx index 38bab934..d9c2aa36 100644 --- a/src/modules/explorer/pages/ProposalDetails/index.tsx +++ b/src/modules/explorer/pages/ProposalDetails/index.tsx @@ -1,6 +1,6 @@ import _ from "lodash" import { Button, Grid, Theme, Typography, useMediaQuery, styled, useTheme, Tooltip } from "@material-ui/core" -import ReactHtmlParser from "react-html-parser" +import parse from "html-react-parser" import { BigNumber } from "bignumber.js" import ProgressBar from "react-customizable-progressbar" import { StatusBadge, statusColors } from "modules/explorer/components/StatusBadge" @@ -655,7 +655,7 @@ export const ProposalDetails: React.FC = () => { {agoraPost && ( - {ReactHtmlParser(agoraPost.post_stream.posts[0].cooked)} + {parse(agoraPost.post_stream.posts[0].cooked)} )} diff --git a/src/modules/lite/explorer/components/DaoCardDetail.tsx b/src/modules/lite/explorer/components/DaoCardDetail.tsx index 22487a0a..b0b26326 100644 --- a/src/modules/lite/explorer/components/DaoCardDetail.tsx +++ b/src/modules/lite/explorer/components/DaoCardDetail.tsx @@ -6,7 +6,7 @@ import { useTezos } from "services/beacon/hooks/useTezos" import { DashboardContext } from "../context/ActionSheets/explorer" import { updateCount } from "services/services/lite/lite-services" import { useHoldersTotalCount } from "../hooks/useHolderTotalCount" -import ReactHtmlParser from "react-html-parser" +import parse from "html-react-parser" const StyledAvatar = styled(Avatar)({ height: 159, @@ -113,7 +113,7 @@ export const DaoCardDetail: React.FC = ({ community, setIsUp - {ReactHtmlParser(community?.description ? community?.description : "")} + {parse(community?.description ? community?.description : "")} diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index cf281101..0ec9462e 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -9,7 +9,7 @@ import dayjs from "dayjs" import LinkIcon from "assets/img/link.svg" import { useNotification } from "modules/common/hooks/useNotification" -import ReactHtmlParser from "react-html-parser" +import parse from "html-react-parser" const Title = styled(Typography)({ fontSize: 32, @@ -220,9 +220,8 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin variant="body2" color="textPrimary" className="proposal-details" - style={{ whiteSpace: "pre-line" }} > - {ReactHtmlParser(poll?.description ? poll?.description : "")} + {parse(poll?.description ? poll?.description : "")} diff --git a/src/modules/lite/explorer/components/ProposalTableRow.tsx b/src/modules/lite/explorer/components/ProposalTableRow.tsx index 41a3bd45..97fc4213 100644 --- a/src/modules/lite/explorer/components/ProposalTableRow.tsx +++ b/src/modules/lite/explorer/components/ProposalTableRow.tsx @@ -4,7 +4,7 @@ import { RowContainer } from "./tables/RowContainer" import { ProposalStatus, TableStatusBadge } from "./ProposalTableRowStatusBadge" import { useHistory } from "react-router" import { Poll } from "models/Polls" -import ReactHtmlParser from "react-html-parser" +import parse from "html-react-parser" import dayjs from "dayjs" export interface ProposalTableRowData { daoId?: string @@ -69,7 +69,7 @@ export const ProposalTableRow: React.FC<{ poll: Poll | any; daoId?: string }> = {poll.description.length > 200 ? stripHtmlTags(poll.description).slice(0, 200) + "..." - : ReactHtmlParser(poll.description)} + : parse(poll.description)} diff --git a/yarn.lock b/yarn.lock index 1a6f9116..946bf5fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7866,10 +7866,10 @@ domutils@^2.5.2, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" -domutils@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== +domutils@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" + integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" @@ -8051,7 +8051,7 @@ entities@^2.0.0: resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.2.0, entities@^4.5.0: +entities@^4.2.0: version "4.5.0" resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -9883,13 +9883,13 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-dom-parser@5.0.8: - version "5.0.8" - resolved "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-5.0.8.tgz" - integrity sha512-vuWiX9EXgu8CJ5m9EP5c7bvBmNSuQVnrY8tl0z0ZX96Uth1IPlYH/8W8VZ/hBajFf18EN+j2pukbCNd01HEd1w== +html-dom-parser@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-5.1.1.tgz#9efb2cfa055f6a71de1bb2f07c5b019db5004f9e" + integrity sha512-+o4Y4Z0CLuyemeccvGN4bAO20aauB2N9tFEAep5x4OW34kV4PTarBHm6RL02afYt2BMKcr0D2Agep8S3nJPIBg== dependencies: domhandler "5.0.3" - htmlparser2 "9.1.0" + htmlparser2 "10.0.0" html-encoding-sniffer@^2.0.1: version "2.0.1" @@ -9928,15 +9928,15 @@ html-minifier-terser@^6.0.2: relateurl "^0.2.7" terser "^5.10.0" -html-react-parser@^5.0.6: - version "5.1.10" - resolved "https://registry.npmjs.org/html-react-parser/-/html-react-parser-5.1.10.tgz" - integrity sha512-gV22PvLij4wdEdtrZbGVC7Zy2OVWnQ0bYhX63S196ZRSx4+K0TuutCreHSXr+saUia8KeKB+2TYziVfijpH4Tw== +html-react-parser@^5.2.8: + version "5.2.8" + resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-5.2.8.tgz#96bc08c669c8ffb1f24e1f256924eaa1de52e4b6" + integrity sha512-09WaI81tbpwhXWeMe1m9VptZVJUcigo0l59zVt+2HUIQT7+baU38/oNhllj6MKhOuGXqh0nrlwOgxbxbm6xXHw== dependencies: domhandler "5.0.3" - html-dom-parser "5.0.8" + html-dom-parser "5.1.1" react-property "2.0.2" - style-to-js "1.1.12" + style-to-js "1.1.19" html-void-elements@^2.0.0: version "2.0.1" @@ -9954,15 +9954,15 @@ html-webpack-plugin@^5.5.0: pretty-error "^4.0.0" tapable "^2.0.0" -htmlparser2@9.1.0: - version "9.1.0" - resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz" - integrity sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ== +htmlparser2@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-10.0.0.tgz#77ad249037b66bf8cc99c6e286ef73b83aeb621d" + integrity sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g== dependencies: domelementtype "^2.3.0" domhandler "^5.0.3" - domutils "^3.1.0" - entities "^4.5.0" + domutils "^3.2.1" + entities "^6.0.0" htmlparser2@^3.9.0: version "3.10.1" @@ -10219,10 +10219,10 @@ inline-style-parser@0.1.1: resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -inline-style-parser@0.2.3: - version "0.2.3" - resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz" - integrity sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g== +inline-style-parser@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.6.tgz#e6bbb5288a635f6284a6249ce754da55c4bd1ff5" + integrity sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg== internal-slot@^1.0.4, internal-slot@^1.0.7: version "1.0.7" @@ -16522,19 +16522,19 @@ style-loader@^3.3.1: resolved "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz" integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== -style-to-js@1.1.12: - version "1.1.12" - resolved "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.12.tgz" - integrity sha512-tv+/FkgNYHI2fvCoBMsqPHh5xovwiw+C3X0Gfnss/Syau0Nr3IqGOJ9XiOYXoPnToHVbllKFf5qCNFJGwFg5mg== +style-to-js@1.1.19: + version "1.1.19" + resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.19.tgz#f3f671e74764c1e8eebfba95a9a672acf5c19011" + integrity sha512-Ev+SgeqiNGT1ufsXyVC5RrJRXdrkRJ1Gol9Qw7Pb72YCKJXrBvP0ckZhBeVSrw2m06DJpei2528uIpjMb4TsoQ== dependencies: - style-to-object "1.0.6" + style-to-object "1.0.12" -style-to-object@1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz" - integrity sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA== +style-to-object@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.12.tgz#03a30e7f4e555bf50845f8b55c7d5bc2248e03f0" + integrity sha512-ddJqYnoT4t97QvN2C95bCgt+m7AAgXjVnkk/jxAfmp7EAB8nnqqZYEbMd3em7/vEomDb2LAQKAy1RFfv41mdNw== dependencies: - inline-style-parser "0.2.3" + inline-style-parser "0.2.6" style-to-object@^0.4.0: version "0.4.4" From d824fdcf96479d746a67015027773f898a3e12d2 Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 08:46:15 +0200 Subject: [PATCH 03/11] fix: prettier formatting for Typography component --- src/modules/lite/explorer/components/ProposalDetailCard.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index 0ec9462e..cf8d34a0 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -216,11 +216,7 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin - + {parse(poll?.description ? poll?.description : "")} From 49a9d93c853ec98d847cf2d612ebb6f0998c8b6c Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 08:50:24 +0200 Subject: [PATCH 04/11] fix: use div instead of Typography for HTML rendering Typography component was flattening block-level HTML elements into inline text. DescriptionContainer (styled div) now properly renders h2, p, ul, hr, etc. --- .../components/ProposalDetailCard.tsx | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index cf8d34a0..6a147fb2 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -23,6 +23,31 @@ const Subtitle = styled(Typography)(({ theme }) => ({ color: theme.palette.primary.light })) +const DescriptionContainer = styled("div")(({ theme }) => ({ + fontSize: 14, + fontWeight: 400, + color: theme.palette.text.secondary, + "& h1, & h2, & h3, & h4, & h5, & h6": { + marginTop: 16, + marginBottom: 8 + }, + "& p": { + marginTop: 8, + marginBottom: 8 + }, + "& ul, & ol": { + marginTop: 8, + marginBottom: 8, + paddingLeft: 24 + }, + "& hr": { + marginTop: 16, + marginBottom: 16, + border: "none", + borderTop: `1px solid ${theme.palette.primary.light}` + } +})) + const LogoItem = styled("img")(({ theme }) => ({ cursor: "pointer", [theme.breakpoints.down("sm")]: { @@ -216,9 +241,9 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin - + {parse(poll?.description ? poll?.description : "")} - + {poll?.externalLink ? ( From dc0aee671f8d78ec8a8f4670e429ed6314095a14 Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 08:54:16 +0200 Subject: [PATCH 05/11] fix: rename HtmlContent to avoid DescriptionContainer conflict --- src/modules/lite/explorer/components/ProposalDetailCard.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index 6a147fb2..50661d34 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -23,7 +23,7 @@ const Subtitle = styled(Typography)(({ theme }) => ({ color: theme.palette.primary.light })) -const DescriptionContainer = styled("div")(({ theme }) => ({ +const HtmlContent = styled("div")(({ theme }) => ({ fontSize: 14, fontWeight: 400, color: theme.palette.text.secondary, @@ -241,9 +241,9 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin - + {parse(poll?.description ? poll?.description : "")} - + {poll?.externalLink ? ( From 7591a8fc19f2845e99fd31547202c8fc2a90a44c Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 08:57:34 +0200 Subject: [PATCH 06/11] fix: add Roboto Flex font family to HTML content --- .../lite/explorer/components/ProposalDetailCard.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index 50661d34..c79d412d 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -24,9 +24,10 @@ const Subtitle = styled(Typography)(({ theme }) => ({ })) const HtmlContent = styled("div")(({ theme }) => ({ - fontSize: 14, - fontWeight: 400, - color: theme.palette.text.secondary, + "fontSize": 14, + "fontWeight": 400, + "fontFamily": "Roboto Flex", + "color": theme.palette.text.secondary, "& h1, & h2, & h3, & h4, & h5, & h6": { marginTop: 16, marginBottom: 8 @@ -241,9 +242,7 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin - - {parse(poll?.description ? poll?.description : "")} - + {parse(poll?.description ? poll?.description : "")} {poll?.externalLink ? ( From ab568a4110629350f0a3dac9d9c2c2866448e035 Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 10:22:52 +0200 Subject: [PATCH 07/11] chore: remove deprecated react-html-parser package --- package.json | 2 -- yarn.lock | 65 ++-------------------------------------------------- 2 files changed, 2 insertions(+), 65 deletions(-) diff --git a/package.json b/package.json index 73aa4c62..678ff717 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "react-customizable-progressbar": "^1.0.2", "react-dom": "^18.2.0", "react-hook-form": "^7.15.4", - "react-html-parser": "^2.0.2", "react-markdown": "^8.0.0", "react-paginate": "^8.2.0", "react-query": "^3.13.0", @@ -102,7 +101,6 @@ "@types/node": "^14.14.35", "@types/react": "^17.0.44", "@types/react-dom": "^18.2.25", - "@types/react-html-parser": "^2.0.2", "@types/react-router-dom": "^5.1.6", "@types/yup": "^0.29.11", "@typescript-eslint/eslint-plugin": "^6.21.0", diff --git a/yarn.lock b/yarn.lock index 946bf5fd..c7d367ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4206,18 +4206,6 @@ resolved "https://registry.npmjs.org/@types/dom-screen-wake-lock/-/dom-screen-wake-lock-1.0.3.tgz" integrity sha512-3Iten7X3Zgwvk6kh6/NRdwN7WbZ760YgFCsF5AxDifltUQzW1RaW+WRmcVtgwFzLjaNu64H+0MPJ13yRa8g3Dw== -"@types/domhandler@^2.4.0", "@types/domhandler@^2.4.3": - version "2.4.5" - resolved "https://registry.npmjs.org/@types/domhandler/-/domhandler-2.4.5.tgz" - integrity sha512-lANhC2grmFG1gBac/8sDAKdIXx+TzAdkJIAjEOSMA+qW3297ybACEbacJnG15aNYfrzDO6fdcoouokqAKsy6aQ== - -"@types/domutils@*": - version "1.7.8" - resolved "https://registry.npmjs.org/@types/domutils/-/domutils-1.7.8.tgz" - integrity sha512-iZGboDV79ibrO3D625p9yD+VgmMDnyJocdIRJvu9Xz66R8SHfOY/XNgdjY5SFoFiLgILceVfSLt7IUhlk1Vhhg== - dependencies: - "@types/domhandler" "^2.4.0" - "@types/eslint@^7.29.0 || ^8.4.1": version "8.56.12" resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz" @@ -4315,16 +4303,6 @@ resolved "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== -"@types/htmlparser2@*": - version "3.10.7" - resolved "https://registry.npmjs.org/@types/htmlparser2/-/htmlparser2-3.10.7.tgz" - integrity sha512-ycBs4PNr9rY9XFFp4WkP+M1UcO49ahn0+9b24cmIY6KWy0w35rW0G8+JTTe9Rp6Wnyqn5SEHZrhCBMa0TIOxBw== - dependencies: - "@types/domhandler" "^2.4.3" - "@types/domutils" "*" - "@types/node" "*" - domhandler "^2.4.0" - "@types/http-errors@*": version "2.0.4" resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz" @@ -4460,14 +4438,6 @@ dependencies: "@types/react" "*" -"@types/react-html-parser@^2.0.2": - version "2.0.6" - resolved "https://registry.npmjs.org/@types/react-html-parser/-/react-html-parser-2.0.6.tgz" - integrity sha512-xqo8u7iqr5eOIulM1BFAlpoBgdhVleLcDHySy8/k7Le9wgdRgZY1UdKtEcdlc2jMS8cqEx8+U4Mz/e5Ves66Fg== - dependencies: - "@types/htmlparser2" "*" - "@types/react" "*" - "@types/react-paginate@^7.1.2": version "7.1.4" resolved "https://registry.npmjs.org/@types/react-paginate/-/react-paginate-7.1.4.tgz" @@ -7811,7 +7781,7 @@ dom-serializer@^2.0.0: domhandler "^5.0.2" entities "^4.2.0" -domelementtype@1, domelementtype@^1.3.1: +domelementtype@1: version "1.3.1" resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== @@ -7835,13 +7805,6 @@ domhandler@5.0.3, domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" -domhandler@^2.3.0, domhandler@^2.4.0: - version "2.4.2" - resolved "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: version "4.3.1" resolved "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz" @@ -7849,7 +7812,7 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" -domutils@^1.5.1, domutils@^1.7.0: +domutils@^1.7.0: version "1.7.0" resolved "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz" integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== @@ -8041,11 +8004,6 @@ enquirer@^2.3.5: ansi-colors "^4.1.1" strip-ansi "^6.0.1" -entities@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - entities@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" @@ -9964,18 +9922,6 @@ htmlparser2@10.0.0: domutils "^3.2.1" entities "^6.0.0" -htmlparser2@^3.9.0: - version "3.10.1" - resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz" @@ -14874,13 +14820,6 @@ react-hook-form@^7.15.4: resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.2.tgz" integrity sha512-y++lwaWjtzDt/XNnyGDQy6goHskFualmDlf+jzEZvjvz6KWDf7EboL7pUvRCzPTJd0EOPpdekYaQLEvvG6m6HA== -react-html-parser@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/react-html-parser/-/react-html-parser-2.0.2.tgz" - integrity sha512-XeerLwCVjTs3njZcgCOeDUqLgNIt/t+6Jgi5/qPsO/krUWl76kWKXMeVs2LhY2gwM6X378DkhLjur0zUQdpz0g== - dependencies: - htmlparser2 "^3.9.0" - react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" From 37a7357fcad16ffe87fbd8dca9982c50f3ff6a4a Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 10:28:21 +0200 Subject: [PATCH 08/11] debug: add visible debug panel to diagnose HTML parsing issue --- .../lite/explorer/components/ProposalDetailCard.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index c79d412d..0acc1bfa 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -242,6 +242,16 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin + {/* DEBUG INFO - Remove after fixing */} +
+
🔍 DEBUG INFO (commit: ab568a4)
+
parse is function: {typeof parse === 'function' ? '✅ YES' : '❌ NO'}
+
parse type: {typeof parse}
+
description length: {poll?.description?.length || 0}
+
description starts with: {poll?.description?.substring(0, 50)}
+
parsed result type: {typeof parse(poll?.description || '')}
+
parsed is array: {Array.isArray(parse(poll?.description || '')) ? 'YES' : 'NO'}
+
{parse(poll?.description ? poll?.description : "")}
From 469847cd9e47483fe07245d63c3b5b9d7c62a5e2 Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 10:38:32 +0200 Subject: [PATCH 09/11] fix: prettier formatting for debug panel --- .../components/ProposalDetailCard.tsx | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/modules/lite/explorer/components/ProposalDetailCard.tsx b/src/modules/lite/explorer/components/ProposalDetailCard.tsx index 0acc1bfa..361288ca 100644 --- a/src/modules/lite/explorer/components/ProposalDetailCard.tsx +++ b/src/modules/lite/explorer/components/ProposalDetailCard.tsx @@ -243,14 +243,26 @@ export const ProposalDetailCard: React.FC<{ poll: Poll | undefined; daoId: strin {/* DEBUG INFO - Remove after fixing */} -
-
🔍 DEBUG INFO (commit: ab568a4)
-
parse is function: {typeof parse === 'function' ? '✅ YES' : '❌ NO'}
+
+
+ 🔍 DEBUG INFO (commit: ab568a4) +
+
parse is function: {typeof parse === "function" ? "✅ YES" : "❌ NO"}
parse type: {typeof parse}
description length: {poll?.description?.length || 0}
description starts with: {poll?.description?.substring(0, 50)}
-
parsed result type: {typeof parse(poll?.description || '')}
-
parsed is array: {Array.isArray(parse(poll?.description || '')) ? 'YES' : 'NO'}
+
parsed result type: {typeof parse(poll?.description || "")}
+
parsed is array: {Array.isArray(parse(poll?.description || "")) ? "YES" : "NO"}
{parse(poll?.description ? poll?.description : "")} From 82138bb27f65db773aaa202018d2a75aa11a3846 Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 11:03:34 +0200 Subject: [PATCH 10/11] debug: Add console logging to trace HTML stripping issue - Log raw API response in useSinglePoll hook - Shows description length, HTML tag presence, and first 100 chars - Will help identify where HTML is being stripped in deploy preview --- src/modules/lite/explorer/hooks/usePoll.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/modules/lite/explorer/hooks/usePoll.tsx b/src/modules/lite/explorer/hooks/usePoll.tsx index c180e054..3feef9d6 100644 --- a/src/modules/lite/explorer/hooks/usePoll.tsx +++ b/src/modules/lite/explorer/hooks/usePoll.tsx @@ -29,6 +29,13 @@ export const useSinglePoll = (pollId: string | undefined, id?: any, community?: return } + // DEBUG: Log raw API response + console.log("🔍 RAW API RESPONSE for pollId:", pollId) + console.log("Description length from API:", record.description?.length || 0) + console.log("Description first 100 chars:", record.description?.substring(0, 100)) + console.log("Has HTML tags:", record.description?.includes("<")) + console.log("Full record:", JSON.stringify(record, null, 2)) + record.timeFormatted = isProposalActive(Number(record.endTime)) record.isActive = record.timeFormatted && !record.timeFormatted.includes("ago") @@ -47,8 +54,10 @@ export const useSinglePoll = (pollId: string | undefined, id?: any, community?: return } } - fetchPoll() + if (pollId) { + fetchPoll() + } return - }, [id, community]) + }, [id, community, pollId, openNotification]) return poll } From e847843b8e5581093e00b9bef8209682cc6fcbf8 Mon Sep 17 00:00:00 2001 From: eightrice Date: Fri, 14 Nov 2025 11:38:12 +0200 Subject: [PATCH 11/11] fix: remove openNotification from useEffect dependencies to prevent infinite loop --- src/modules/lite/explorer/hooks/usePoll.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/lite/explorer/hooks/usePoll.tsx b/src/modules/lite/explorer/hooks/usePoll.tsx index 3feef9d6..02548512 100644 --- a/src/modules/lite/explorer/hooks/usePoll.tsx +++ b/src/modules/lite/explorer/hooks/usePoll.tsx @@ -58,6 +58,6 @@ export const useSinglePoll = (pollId: string | undefined, id?: any, community?: fetchPoll() } return - }, [id, community, pollId, openNotification]) + }, [id, community, pollId]) return poll }