diff --git a/client/package-lock.json b/client/package-lock.json index 0ba8c34..edc30d8 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -19,6 +19,7 @@ "@mui/material": "^6.1.0", "@types/uuid": "^9.0.7", "axios": "^1.6.7", + "dompurify": "^3.2.3", "esbuild": "^0.23.1", "gift-pegjs": "^1.0.2", "jest-environment-jsdom": "^29.7.0", @@ -4705,6 +4706,13 @@ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -6230,6 +6238,15 @@ "node": ">=12" } }, + "node_modules/dompurify": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz", + "integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -10818,9 +10835,9 @@ } }, "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", diff --git a/client/package.json b/client/package.json index 6476a10..052063d 100644 --- a/client/package.json +++ b/client/package.json @@ -23,6 +23,7 @@ "@mui/material": "^6.1.0", "@types/uuid": "^9.0.7", "axios": "^1.6.7", + "dompurify": "^3.2.3", "esbuild": "^0.23.1", "gift-pegjs": "^1.0.2", "jest-environment-jsdom": "^29.7.0", diff --git a/client/src/__tests__/components/GiftTemplate/templates/AnswerIcon.test.tsx b/client/src/__tests__/components/GiftTemplate/templates/AnswerIcon.test.tsx index 2727893..0a9226b 100644 --- a/client/src/__tests__/components/GiftTemplate/templates/AnswerIcon.test.tsx +++ b/client/src/__tests__/components/GiftTemplate/templates/AnswerIcon.test.tsx @@ -2,10 +2,11 @@ import React from 'react'; import { render } from '@testing-library/react'; import '@testing-library/jest-dom'; import AnswerIcon from 'src/components/GiftTemplate/templates/AnswerIcon'; +import DOMPurify from 'dompurify'; describe('AnswerIcon', () => { test('renders correct icon when correct is true', () => { - const { container } = render(
); + const { container } = render(
); const svgElement = container.querySelector('svg'); expect(svgElement).toBeInTheDocument(); @@ -20,7 +21,7 @@ describe('AnswerIcon', () => { }); test('renders incorrect icon when correct is false', () => { - const { container } = render(
); + const { container } = render(
); const svgElement = container.querySelector('svg'); expect(svgElement).toBeInTheDocument(); diff --git a/client/src/components/GiftTemplate/GIFTTemplatePreview.tsx b/client/src/components/GiftTemplate/GIFTTemplatePreview.tsx index 4202b80..51dbd3f 100644 --- a/client/src/components/GiftTemplate/GIFTTemplatePreview.tsx +++ b/client/src/components/GiftTemplate/GIFTTemplatePreview.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react'; import Template, { ErrorTemplate } from './templates'; import { parse } from 'gift-pegjs'; import './styles.css'; +import DOMPurify from 'dompurify'; interface GIFTTemplatePreviewProps { questions: string[]; @@ -73,7 +74,7 @@ const GIFTTemplatePreview: React.FC = ({
{error}
) : isPreviewReady ? (
-
+
) : (
Chargement de la prévisualisation...
diff --git a/client/src/components/Questions/MultipleChoiceQuestion/MultipleChoiceQuestion.tsx b/client/src/components/Questions/MultipleChoiceQuestion/MultipleChoiceQuestion.tsx index 5f0e57d..4957d11 100644 --- a/client/src/components/Questions/MultipleChoiceQuestion/MultipleChoiceQuestion.tsx +++ b/client/src/components/Questions/MultipleChoiceQuestion/MultipleChoiceQuestion.tsx @@ -4,6 +4,7 @@ import '../questionStyle.css'; import { Button } from '@mui/material'; import textType, { formatLatex } from '../../GiftTemplate/templates/TextType'; import { TextFormat } from '../../GiftTemplate/templates/types'; +import DOMPurify from 'dompurify'; // import Latex from 'react-latex'; type Choices = { @@ -39,7 +40,7 @@ const MultipleChoiceQuestion: React.FC = (props) => { return (
-
+
{choices.map((choice, i) => { @@ -56,7 +57,7 @@ const MultipleChoiceQuestion: React.FC = (props) => { (choice.isCorrect ? '✅' : '❌')}
{alphabet[i]}
-
+
{choice.feedback && showAnswer && ( diff --git a/client/src/components/Questions/NumericalQuestion/NumericalQuestion.tsx b/client/src/components/Questions/NumericalQuestion/NumericalQuestion.tsx index 449e4c7..7a9cec7 100644 --- a/client/src/components/Questions/NumericalQuestion/NumericalQuestion.tsx +++ b/client/src/components/Questions/NumericalQuestion/NumericalQuestion.tsx @@ -4,6 +4,7 @@ import '../questionStyle.css'; import { Button, TextField } from '@mui/material'; import textType from '../../GiftTemplate/templates/TextType'; import { TextFormat } from '../../GiftTemplate/templates/types'; +import DOMPurify from 'dompurify'; type CorrectAnswer = { numberHigh?: number; @@ -34,7 +35,7 @@ const NumericalQuestion: React.FC = (props) => { return (
-
+
{showAnswer ? ( <> diff --git a/client/src/components/Questions/ShortAnswerQuestion/ShortAnswerQuestion.tsx b/client/src/components/Questions/ShortAnswerQuestion/ShortAnswerQuestion.tsx index 3f134d6..28639c4 100644 --- a/client/src/components/Questions/ShortAnswerQuestion/ShortAnswerQuestion.tsx +++ b/client/src/components/Questions/ShortAnswerQuestion/ShortAnswerQuestion.tsx @@ -4,6 +4,7 @@ import '../questionStyle.css'; import { Button, TextField } from '@mui/material'; import textType from '../../GiftTemplate/templates/TextType'; import { TextFormat } from '../../GiftTemplate/templates/types'; +import DOMPurify from 'dompurify'; type Choices = { feedback: { format: string; text: string } | null; @@ -28,7 +29,7 @@ const ShortAnswerQuestion: React.FC = (props) => { return (
-
+
{showAnswer ? ( <> diff --git a/client/src/components/Questions/TrueFalseQuestion/TrueFalseQuestion.tsx b/client/src/components/Questions/TrueFalseQuestion/TrueFalseQuestion.tsx index 4597d6f..18b7038 100644 --- a/client/src/components/Questions/TrueFalseQuestion/TrueFalseQuestion.tsx +++ b/client/src/components/Questions/TrueFalseQuestion/TrueFalseQuestion.tsx @@ -4,6 +4,7 @@ import '../questionStyle.css'; import { Button } from '@mui/material'; import textType from '../../GiftTemplate/templates/TextType'; import { TextFormat } from '../../GiftTemplate/templates/types'; +import DOMPurify from 'dompurify'; interface Props { questionContent: TextFormat; @@ -27,7 +28,7 @@ const TrueFalseQuestion: React.FC = (props) => { return (
-
+
+ {showScrollButton && ( + + )}
); }; +const scrollToTopButtonStyle: CSSProperties = { + position: 'fixed', + bottom: '40px', + right: '50px', + padding: '10px', + fontSize: '16px', + color: 'white', + backgroundColor: '#5271ff', + border: 'none', + cursor: 'pointer', + zIndex: 1000, +}; + export default QuizForm; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..3c251e0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "EvalueTonSavoir", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "dompurify": "^3.2.3" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/dompurify": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz", + "integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a969a9f --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "dompurify": "^3.2.3" + } +}