Skip to content

Commit 7ef8b52

Browse files
chore: Add a HTMLRender component to render server side in HTML
1 parent 3481ac9 commit 7ef8b52

8 files changed

Lines changed: 64 additions & 17 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"bootstrap-tagsinput": "^0.7.1",
8282
"chosen-js": "^1.8.7",
8383
"crypto-js": "^3.1.9-1",
84+
"dompurify": "^3.4.11",
8485
"easymde": "^2.18.0",
8586
"font-awesome": "^4.7.0",
8687
"formik": "^2.2.9",
@@ -95,6 +96,7 @@
9596
"moment": "^2.29.4",
9697
"moment-timezone": "^0.5.21",
9798
"popper.js": "^1.14.3",
99+
"prop-types": "^15.8.1",
98100
"pure": "^2.85.0",
99101
"pwstrength-bootstrap": "^3.0.10",
100102
"react-otp-input": "^3.1.1",

resources/js/login/components/email_input_form.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Paper from "@material-ui/core/Paper";
33
import TextField from "@material-ui/core/TextField";
44
import Button from "@material-ui/core/Button";
55
import styles from "../login.module.scss";
6+
import HTMLRender from "../../shared/HTMLRender";
67

78
const EmailInputForm = ({
89
value,
@@ -49,10 +50,9 @@ const EmailInputForm = ({
4950
)}
5051
</Paper>
5152
{emailError != "" && (
52-
<p
53-
className={styles.error_label}
54-
dangerouslySetInnerHTML={{ __html: emailError }}
55-
></p>
53+
<HTMLRender component="p" className={styles.error_label}>
54+
{emailError}
55+
</HTMLRender>
5656
)}
5757
</>
5858
);

resources/js/login/components/otp_input_form.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Button from "@material-ui/core/Button";
44
import Link from "@material-ui/core/Link";
55
import OtpInput from "react-otp-input";
66
import styles from "../login.module.scss";
7+
import HTMLRender from "../../shared/HTMLRender";
78

89
const OTPInputForm = ({
910
disableInput,
@@ -52,10 +53,9 @@ const OTPInputForm = ({
5253
/>
5354
</div>
5455
{otpError && (
55-
<p
56-
className={styles.error_label}
57-
dangerouslySetInnerHTML={{ __html: otpError }}
58-
></p>
56+
<HTMLRender component="p" className={styles.error_label}>
57+
{otpError}
58+
</HTMLRender>
5959
)}
6060
<div>
6161
<Button

resources/js/login/components/password_input_form.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import InputAdornment from "@material-ui/core/InputAdornment";
1111
import IconButton from "@material-ui/core/IconButton";
1212
import ExistingAccountActions from "./existing_account_actions";
1313
import styles from "../login.module.scss";
14+
import HTMLRender from "../../shared/HTMLRender";
1415

1516
const PasswordInputForm = ({
1617
formAction,
@@ -82,10 +83,9 @@ const PasswordInputForm = ({
8283
}
8384

8485
return (
85-
<p
86-
className={styles.error_label}
87-
dangerouslySetInnerHTML={{ __html: passwordError }}
88-
/>
86+
<HTMLRender component="p" className={styles.error_label}>
87+
{passwordError}
88+
</HTMLRender>
8989
);
9090
};
9191

resources/js/login/components/recovery_code_form.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import TextField from '@material-ui/core/TextField';
33
import Button from '@material-ui/core/Button';
44
import Link from '@material-ui/core/Link';
55
import styles from '../login.module.scss';
6+
import HTMLRender from '../../shared/HTMLRender';
67

78
const RecoveryCodeForm = ({
89
recoveryCode,
@@ -50,9 +51,11 @@ const RecoveryCodeForm = ({
5051
onChange={onRecoveryCodeChange}
5152
error={!!recoveryError}
5253
/>
53-
{recoveryError &&
54-
<p className={styles.error_label} dangerouslySetInnerHTML={{__html: recoveryError}}></p>
55-
}
54+
{recoveryError && (
55+
<HTMLRender component="p" className={styles.error_label}>
56+
{recoveryError}
57+
</HTMLRender>
58+
)}
5659
<div>
5760
<Button variant="contained"
5861
disabled={disableInput || recoveryCode === ''}

resources/js/login/components/two_factor_form.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Checkbox from '@material-ui/core/Checkbox';
66
import OtpInput from 'react-otp-input';
77
import {formatTime} from '../../utils';
88
import styles from '../login.module.scss';
9+
import HTMLRender from '../../shared/HTMLRender';
910

1011
// Cooldown applied to the resend action to avoid hammering the resend endpoint
1112
// (the backend also rate-limits server-side).
@@ -89,7 +90,9 @@ const TwoFactorForm = ({
8990
/>
9091
</div>
9192
{otpError &&
92-
<p className={styles.error_label} dangerouslySetInnerHTML={{__html: otpError}}></p>
93+
<HTMLRender component="p" className={styles.error_label}>
94+
{otpError}
95+
</HTMLRender>
9396
}
9497
<p className={styles.countdown}>
9598
{expired

resources/js/shared/HTMLRender.jsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* eslint-disable react/no-danger */
2+
import PropTypes from "prop-types";
3+
import DOMPurify from "dompurify";
4+
5+
const HTMLRender = ({ children, className, style, component = "div" }) => {
6+
const html = DOMPurify.sanitize(children || "");
7+
const Component = component;
8+
9+
return (
10+
<Component
11+
style={style}
12+
className={className}
13+
dangerouslySetInnerHTML={{ __html: html }}
14+
/>
15+
);
16+
};
17+
18+
HTMLRender.propTypes = {
19+
children: PropTypes.string,
20+
className: PropTypes.string,
21+
style: PropTypes.shape({
22+
[PropTypes.string]: PropTypes.string
23+
}),
24+
component: PropTypes.elementType
25+
};
26+
27+
export default HTMLRender;

yarn.lock

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2047,6 +2047,11 @@
20472047
dependencies:
20482048
"@types/estree" "*"
20492049

2050+
"@types/trusted-types@^2.0.7":
2051+
version "2.0.7"
2052+
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
2053+
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
2054+
20502055
"@types/ws@^8.5.5":
20512056
version "8.18.1"
20522057
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9"
@@ -3645,6 +3650,13 @@ domexception@^2.0.1:
36453650
dependencies:
36463651
webidl-conversions "^5.0.0"
36473652

3653+
dompurify@^3.4.11:
3654+
version "3.4.11"
3655+
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.4.11.tgz#29c8ba496475f279ef4015784068452fb14a0680"
3656+
integrity sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==
3657+
optionalDependencies:
3658+
"@types/trusted-types" "^2.0.7"
3659+
36483660
dotenv-defaults@^1.0.2:
36493661
version "1.1.1"
36503662
resolved "https://registry.yarnpkg.com/dotenv-defaults/-/dotenv-defaults-1.1.1.tgz#032c024f4b5906d9990eb06d722dc74cc60ec1bd"
@@ -6558,7 +6570,7 @@ prompts@^2.0.1:
65586570
kleur "^3.0.3"
65596571
sisteransi "^1.0.5"
65606572

6561-
prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
6573+
prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
65626574
version "15.8.1"
65636575
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
65646576
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==

0 commit comments

Comments
 (0)