mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-02-23 15:34:21 +01:00
feat: purify injected html in post & comments
This commit is contained in:
@@ -52,7 +52,6 @@ async function getPaymetRequestForItem(lightning_address, amount_in_sat) {
|
||||
return axios
|
||||
.get(lnurlCallbackUrl, { params: { amount } })
|
||||
.then((prResponse) => {
|
||||
console.log(prResponse.data);
|
||||
return prResponse.data.pr;
|
||||
});
|
||||
}
|
||||
|
||||
30
package-lock.json
generated
30
package-lock.json
generated
@@ -41,6 +41,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"crypto": "^1.0.1",
|
||||
"dayjs": "^1.11.1",
|
||||
"dompurify": "^2.3.10",
|
||||
"env-cmd": "^10.1.0",
|
||||
"express": "^4.18.1",
|
||||
"express-session": "^1.17.3",
|
||||
@@ -111,6 +112,7 @@
|
||||
"@storybook/testing-library": "^0.0.10",
|
||||
"@tailwindcss/forms": "^0.5.0",
|
||||
"@types/chance": "^1.1.3",
|
||||
"@types/dompurify": "^2.3.3",
|
||||
"@types/fslightbox-react": "^1.4.2",
|
||||
"@types/lodash.debounce": "^4.0.7",
|
||||
"@types/lodash.throttle": "^4.1.7",
|
||||
@@ -15177,6 +15179,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/direction/-/direction-1.0.0.tgz",
|
||||
"integrity": "sha512-et1wmqXm/5smJ8lTJfBnwD12/2Y7eVJLKbuaRT0h2xaKAoo1h8Dz2Io22GObDLFwxY1ddXRTLH3Gq5v44Fl/2w=="
|
||||
},
|
||||
"node_modules/@types/dompurify": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.3.3.tgz",
|
||||
"integrity": "sha512-nnVQSgRVuZ/843oAfhA25eRSNzUFcBPk/LOiw5gm8mD9/X7CNcbRkQu/OsjCewO8+VIYfPxUnXvPEVGenw14+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/trusted-types": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz",
|
||||
@@ -21637,6 +21648,11 @@
|
||||
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
|
||||
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "2.3.10",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz",
|
||||
"integrity": "sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g=="
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
@@ -79432,6 +79448,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/direction/-/direction-1.0.0.tgz",
|
||||
"integrity": "sha512-et1wmqXm/5smJ8lTJfBnwD12/2Y7eVJLKbuaRT0h2xaKAoo1h8Dz2Io22GObDLFwxY1ddXRTLH3Gq5v44Fl/2w=="
|
||||
},
|
||||
"@types/dompurify": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.3.3.tgz",
|
||||
"integrity": "sha512-nnVQSgRVuZ/843oAfhA25eRSNzUFcBPk/LOiw5gm8mD9/X7CNcbRkQu/OsjCewO8+VIYfPxUnXvPEVGenw14+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/trusted-types": "*"
|
||||
}
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz",
|
||||
@@ -84640,6 +84665,11 @@
|
||||
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
|
||||
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
|
||||
},
|
||||
"dompurify": {
|
||||
"version": "2.3.10",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz",
|
||||
"integrity": "sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g=="
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"crypto": "^1.0.1",
|
||||
"dayjs": "^1.11.1",
|
||||
"dompurify": "^2.3.10",
|
||||
"env-cmd": "^10.1.0",
|
||||
"express": "^4.18.1",
|
||||
"express-session": "^1.17.3",
|
||||
@@ -162,6 +163,7 @@
|
||||
"@storybook/testing-library": "^0.0.10",
|
||||
"@tailwindcss/forms": "^0.5.0",
|
||||
"@types/chance": "^1.1.3",
|
||||
"@types/dompurify": "^2.3.3",
|
||||
"@types/fslightbox-react": "^1.4.2",
|
||||
"@types/lodash.debounce": "^4.0.7",
|
||||
"@types/lodash.throttle": "^4.1.7",
|
||||
|
||||
@@ -33,6 +33,7 @@ type Props = {
|
||||
direction?: 'horizontal' | 'vertical'
|
||||
disableCounter?: boolean
|
||||
disableShake?: boolean
|
||||
hideVotesCoun?: boolean
|
||||
dense?: boolean
|
||||
size?: 'sm' | 'md'
|
||||
resetCounterOnRelease?: boolean
|
||||
@@ -59,6 +60,7 @@ export default function VoteButton({
|
||||
direction = 'horizontal',
|
||||
disableCounter = false,
|
||||
disableShake = false,
|
||||
hideVotesCoun = false,
|
||||
dense = false,
|
||||
resetCounterOnRelease: resetCounterOnReleaseProp = false,
|
||||
...props }: Props) {
|
||||
@@ -221,7 +223,7 @@ export default function VoteButton({
|
||||
${direction === 'vertical' ?
|
||||
dense ? "py-4 px-12" : "py-8 px-20"
|
||||
:
|
||||
dense ? "py-4 px-8" : "p-8"}
|
||||
dense ? "py-4 px-8" : "p-8 min-w-[80px]"}
|
||||
${voteCntRef.current > 0 && "outline"} active:outline outline-1 outline-red-500
|
||||
${btnShakeClass}
|
||||
`}
|
||||
@@ -246,7 +248,7 @@ export default function VoteButton({
|
||||
<MdLocalFireDepartment
|
||||
className={`text-body2 ${incrementsCount ? "text-red-600" : "text-gray-400"}`}
|
||||
|
||||
/><span className="align-middle w-[4ch]"> {numberFormatter(votes + voteCnt)}</span>
|
||||
/>{!hideVotesCoun && <span className="align-middle w-[4ch]"> {numberFormatter(votes + voteCnt)}</span>}
|
||||
</div>
|
||||
<AnimatePresence>
|
||||
{btnState === 'loading' &&
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { marked } from "marked";
|
||||
import { BiComment } from "react-icons/bi";
|
||||
import VotesCount from "src/Components/VotesCount/VotesCount";
|
||||
import VoteButton from "src/Components/VoteButton/VoteButton";
|
||||
import Header from "src/features/Posts/Components/PostCard/Header/Header";
|
||||
import { Comment } from "../types";
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
|
||||
interface Props {
|
||||
@@ -15,11 +16,14 @@ export default function CommentCard({ comment, canReply, onReply }: Props) {
|
||||
return (
|
||||
<div className="border rounded-12 p-24">
|
||||
<Header author={comment.author} date={new Date(comment.created_at).toISOString()} />
|
||||
<p className="text-body4 mt-16 whitespace-pre-line" dangerouslySetInnerHTML={{ __html: marked.parse(comment.body) }}>
|
||||
<div
|
||||
className="text-body4 mt-16 whitespace-pre-line"
|
||||
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(marked.parse(comment.body)) }}
|
||||
>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-24 mt-16 items-center">
|
||||
<VotesCount count={0} />
|
||||
<VoteButton votes={0} hideVotesCoun onVote={(value, config) => console.log('Voting amount ' + value)} />
|
||||
{canReply && <button
|
||||
className="text-gray-600 font-medium hover:bg-gray-100 py-8 px-12 rounded-8"
|
||||
onClick={onReply}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||
import { useAppSelector } from "src/utils/hooks";
|
||||
import { useUpdateStory } from './useUpdateStory'
|
||||
import { FaPen } from "react-icons/fa";
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
|
||||
interface Props {
|
||||
@@ -66,7 +67,10 @@ export default function StoryPageContent({ story }: Props) {
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<div className={`mt-42 ${styles.body}`} dangerouslySetInnerHTML={{ __html: marked.parse(story.body) }}>
|
||||
<div
|
||||
className={`mt-42 ${styles.body}`}
|
||||
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(marked.parse(story.body)) }}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div id="comments" className="mt-10 comments_col">
|
||||
|
||||
@@ -36,7 +36,7 @@ export function createRoute(options: RouteOptions) {
|
||||
|
||||
|
||||
if (options.type === 'post')
|
||||
return `/blog/post/${options.postType}/${options.id}`
|
||||
return `/blog/post/${options.postType.toLowerCase()}/${options.id}`
|
||||
+ (options.title ? `/${toSlug(options.title)}` : "");
|
||||
|
||||
if (options.type === 'story')
|
||||
|
||||
Reference in New Issue
Block a user