Clean description with DOMPurify

This commit is contained in:
Justin Edmund 2023-07-04 16:56:54 -07:00
parent 277a248ba1
commit ed01ea6955
3 changed files with 35 additions and 13 deletions

View file

@ -2,12 +2,8 @@ import React, { useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { useSnapshot } from 'valtio'
import { useTranslation } from 'next-i18next'
import classNames from 'classnames'
import clonedeep from 'lodash.clonedeep'
import Linkify from 'react-linkify'
import LiteYouTubeEmbed from 'react-lite-youtube-embed'
import reactStringReplace from 'react-string-replace'
import DOMPurify from 'dompurify'
import Button from '~components/common/Button'
import SegmentedControl from '~components/common/SegmentedControl'
@ -55,15 +51,14 @@ const PartyFooter = (props: Props) => {
// State: Data
const [remixes, setRemixes] = useState<Party[]>([])
const [embeddedDescription, setEmbeddedDescription] =
useState<React.ReactNode>()
const [sanitizedDescription, setSanitizedDescription] = useState('')
useEffect(() => {
if (partySnapshot.description) {
const purified = DOMPurify.sanitize(partySnapshot.description)
setSanitizedDescription(purified)
} else {
setEmbeddedDescription('')
setSanitizedDescription('')
}
}, [partySnapshot.description])
@ -211,14 +206,17 @@ const PartyFooter = (props: Props) => {
)
const descriptionSection = (
<section className={styles.description}>
<>
{partySnapshot &&
partySnapshot.description &&
partySnapshot.description.length > 0 && (
<Linkify>{embeddedDescription}</Linkify>
<section
className={styles.description}
dangerouslySetInnerHTML={{ __html: sanitizedDescription }}
/>
)}
{(!partySnapshot || !partySnapshot.description) && (
<div className={styles.noDescription}>
<section className={styles.noDescription}>
<h3>{t('footer.description.empty')}</h3>
{props.editable && (
<EditPartyModal
@ -234,9 +232,9 @@ const PartyFooter = (props: Props) => {
/>
</EditPartyModal>
)}
</div>
)}
</section>
)}
</>
)
const remixesSection = (

22
package-lock.json generated
View file

@ -24,6 +24,7 @@
"cmdk": "^0.2.0",
"cookies-next": "^2.1.1",
"date-fns": "^2.29.3",
"dompurify": "^3.0.4",
"fast-deep-equal": "^3.1.3",
"fix-date": "^1.1.6",
"i18next": "^21.6.13",
@ -65,6 +66,7 @@
"@storybook/nextjs": "latest",
"@storybook/react": "latest",
"@storybook/testing-library": "latest",
"@types/dompurify": "^3.0.2",
"@types/lodash.clonedeep": "^4.5.6",
"@types/lodash.debounce": "^4.0.6",
"@types/node": "17.0.11",
@ -7041,6 +7043,15 @@
"integrity": "sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==",
"dev": true
},
"node_modules/@types/dompurify": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.2.tgz",
"integrity": "sha512-YBL4ziFebbbfQfH5mlC+QTJsvh0oJUrWbmxKMyEdL7emlHJqGR2Qb34TEFKj+VCayBvjKy3xczMFNhugThUsfQ==",
"dev": true,
"dependencies": {
"@types/trusted-types": "*"
}
},
"node_modules/@types/ejs": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz",
@ -7389,6 +7400,12 @@
"@types/node": "*"
}
},
"node_modules/@types/trusted-types": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
"dev": true
},
"node_modules/@types/unist": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
@ -10577,6 +10594,11 @@
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/dompurify": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.4.tgz",
"integrity": "sha512-ae0mA+Qiqp6C29pqZX3fQgK+F91+F7wobM/v8DRzDqJdZJELXiFUx4PP4pK/mzUS0xkiSEx3Ncd9gr69jg3YsQ=="
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",

View file

@ -31,6 +31,7 @@
"cmdk": "^0.2.0",
"cookies-next": "^2.1.1",
"date-fns": "^2.29.3",
"dompurify": "^3.0.4",
"fast-deep-equal": "^3.1.3",
"fix-date": "^1.1.6",
"i18next": "^21.6.13",
@ -72,6 +73,7 @@
"@storybook/nextjs": "latest",
"@storybook/react": "latest",
"@storybook/testing-library": "latest",
"@types/dompurify": "^3.0.2",
"@types/lodash.clonedeep": "^4.5.6",
"@types/lodash.debounce": "^4.0.6",
"@types/node": "17.0.11",