Modification Katex, prise en charge markdown, ajout description

This commit is contained in:
Melanie St-Hilaire 2024-04-16 12:14:20 -04:00
parent 2893683f1c
commit 7497abd712
7 changed files with 46 additions and 51 deletions

View file

@ -137,14 +137,19 @@ const GiftCheatSheet: React.FC = () => {
</div> </div>
<div className="question-type"> <div className="question-type">
<h4> 8. LaTeX </h4> <h4> 8. LaTeX et Markdown</h4>
<p> <p>
Le format LaTeX est supporté dans cette application. Vous devez cependant penser Les format LaTeX et markdown sont supportés dans cette application. Vous devez cependant penser
à 'échapper' les caractères spéciaux mentionnés plus haut. à 'échapper' les caractères spéciaux mentionnés plus haut.
</p> </p>
<p>Exemple d'équation:</p> <p>Exemple d'équation:</p>
<pre> <pre>
<code className="question-code-block">{'$$x\\= \\frac\\{y^2\\}\\{4\\}$$'}</code> <code className="question-code-block selectable-text">{'$$x\\= \\frac\\{y^2\\}\\{4\\}$$'}</code>
<code className="question-code-block selectable-text">{'\n$x\\= \\frac\\{y^2\\}\\{4\\}$'}</code>
</pre>
<p>Exemple de texte Markdown:</p>
<pre>
<code className="question-code-block selectable-text">{'[markdown]Grâce à la balise markdown, Il est possible d\'insérer du texte *italique*, **gras**, du `code` et bien plus.'}</code>
</pre> </pre>
</div> </div>

View file

@ -9,6 +9,7 @@ interface TextTypeOptions extends TemplateOptions {
function formatLatex(text: string): string { function formatLatex(text: string): string {
return text return text
.replace(/\$\$(.*?)\$\$/g, (_, inner) => katex.renderToString(inner, { displayMode: true })) .replace(/\$\$(.*?)\$\$/g, (_, inner) => katex.renderToString(inner, { displayMode: true }))
.replace(/\$(.*?)\$/g, (_, inner) => katex.renderToString(inner, { displayMode: false }))
.replace(/\\\[(.*?)\\\]/g, (_, inner) => katex.renderToString(inner, { displayMode: true })) .replace(/\\\[(.*?)\\\]/g, (_, inner) => katex.renderToString(inner, { displayMode: true }))
.replace(/\\\((.*?)\\\)/g, (_, inner) => .replace(/\\\((.*?)\\\)/g, (_, inner) =>
katex.renderToString(inner, { displayMode: false }) katex.renderToString(inner, { displayMode: false })

View file

@ -1,8 +1,10 @@
// MultipleChoiceQuestion.tsx // MultipleChoiceQuestion.tsx
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import Latex from 'react-latex';
import '../questionStyle.css'; import '../questionStyle.css';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import TextType from '../../GiftTemplate/templates/TextType';
import { TextFormat } from '../../GiftTemplate/templates/types';
import Latex from 'react-latex';
type Choices = { type Choices = {
feedback: { format: string; text: string } | null; feedback: { format: string; text: string } | null;
@ -12,8 +14,7 @@ type Choices = {
}; };
interface Props { interface Props {
questionTitle: string | null; questionContent: TextFormat;
questionContent: string;
choices: Choices[]; choices: Choices[];
globalFeedback?: string | undefined; globalFeedback?: string | undefined;
handleOnSubmitAnswer?: (answer: string) => void; handleOnSubmitAnswer?: (answer: string) => void;
@ -21,22 +22,24 @@ interface Props {
} }
const MultipleChoiceQuestion: React.FC<Props> = (props) => { const MultipleChoiceQuestion: React.FC<Props> = (props) => {
const { questionTitle, questionContent, choices, showAnswer, handleOnSubmitAnswer, globalFeedback } = props; const { questionContent, choices, showAnswer, handleOnSubmitAnswer, globalFeedback } = props;
const [answer, setAnswer] = useState<string>(); const [answer, setAnswer] = useState<string>();
useEffect(() => {
setAnswer(undefined);
}, [questionContent]);
const handleOnClickAnswer = (choice: string) => { const handleOnClickAnswer = (choice: string) => {
setAnswer(choice); setAnswer(choice);
}; };
const alpha = Array.from(Array(26)).map((_e, i) => i + 65); const alpha = Array.from(Array(26)).map((_e, i) => i + 65);
const alphabet = alpha.map((x) => String.fromCharCode(x)); const alphabet = alpha.map((x) => String.fromCharCode(x));
return ( return (
<div className="question-container"> <div className="question-container">
<div className="title mb-1 text-center align-h-center">
{questionTitle}
</div>
<div className="question content"> <div className="question content">
<Latex>{questionContent}</Latex> <div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
</div> </div>
<div className="choices-wrapper mb-1"> <div className="choices-wrapper mb-1">
{choices.map((choice, i) => { {choices.map((choice, i) => {

View file

@ -1,8 +1,9 @@
// NumericalQuestion.tsx // NumericalQuestion.tsx
import React, { useState } from 'react'; import React, { useState } from 'react';
import Latex from 'react-latex';
import '../questionStyle.css'; import '../questionStyle.css';
import { Button, TextField } from '@mui/material'; import { Button, TextField } from '@mui/material';
import TextType from '../../GiftTemplate/templates/TextType';
import { TextFormat } from '../../GiftTemplate/templates/types';
type CorrectAnswer = { type CorrectAnswer = {
numberHigh?: number; numberHigh?: number;
@ -12,8 +13,7 @@ type CorrectAnswer = {
}; };
interface Props { interface Props {
questionTitle: string | null; questionContent: TextFormat;
questionContent: string;
correctAnswers: CorrectAnswer; correctAnswers: CorrectAnswer;
globalFeedback?: string | undefined; globalFeedback?: string | undefined;
handleOnSubmitAnswer?: (answer: number) => void; handleOnSubmitAnswer?: (answer: number) => void;
@ -21,7 +21,7 @@ interface Props {
} }
const NumericalQuestion: React.FC<Props> = (props) => { const NumericalQuestion: React.FC<Props> = (props) => {
const { questionTitle, questionContent, correctAnswers, showAnswer, handleOnSubmitAnswer, globalFeedback } = const { questionContent, correctAnswers, showAnswer, handleOnSubmitAnswer, globalFeedback } =
props; props;
const [answer, setAnswer] = useState<number>(); const [answer, setAnswer] = useState<number>();
@ -33,11 +33,8 @@ const NumericalQuestion: React.FC<Props> = (props) => {
return ( return (
<div className="question-wrapper"> <div className="question-wrapper">
<div className="title mb-1 text-center center-h-align">
{questionTitle}
</div>
<div> <div>
<Latex>{questionContent}</Latex> <div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
</div> </div>
{showAnswer ? ( {showAnswer ? (
<> <>
@ -49,8 +46,8 @@ const NumericalQuestion: React.FC<Props> = (props) => {
<div className="answer-wrapper mb-1"> <div className="answer-wrapper mb-1">
<TextField <TextField
type="number" type="number"
id={questionContent} id={questionContent.text}
name={questionContent} name={questionContent.text}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setAnswer(e.target.valueAsNumber); setAnswer(e.target.valueAsNumber);
}} }}

View file

@ -30,8 +30,7 @@ const Question: React.FC<QuestionProps> = ({
case 'TF': case 'TF':
questionTypeComponent = ( questionTypeComponent = (
<TrueFalseQuestion <TrueFalseQuestion
questionTitle={question.title} questionContent={question.stem}
questionContent={question.stem.text}
correctAnswer={question.isTrue} correctAnswer={question.isTrue}
handleOnSubmitAnswer={handleOnSubmitAnswer} handleOnSubmitAnswer={handleOnSubmitAnswer}
showAnswer={showAnswer} showAnswer={showAnswer}
@ -42,8 +41,7 @@ const Question: React.FC<QuestionProps> = ({
case 'MC': case 'MC':
questionTypeComponent = ( questionTypeComponent = (
<MultipleChoiceQuestion <MultipleChoiceQuestion
questionTitle={question.title} questionContent={question.stem}
questionContent={question.stem.text}
choices={question.choices} choices={question.choices}
handleOnSubmitAnswer={handleOnSubmitAnswer} handleOnSubmitAnswer={handleOnSubmitAnswer}
showAnswer={showAnswer} showAnswer={showAnswer}
@ -56,8 +54,7 @@ const Question: React.FC<QuestionProps> = ({
if (!Array.isArray(question.choices)) { if (!Array.isArray(question.choices)) {
questionTypeComponent = ( questionTypeComponent = (
<NumericalQuestion <NumericalQuestion
questionTitle={question.title} questionContent={question.stem}
questionContent={question.stem.text}
correctAnswers={question.choices} correctAnswers={question.choices}
handleOnSubmitAnswer={handleOnSubmitAnswer} handleOnSubmitAnswer={handleOnSubmitAnswer}
showAnswer={showAnswer} showAnswer={showAnswer}
@ -67,8 +64,7 @@ const Question: React.FC<QuestionProps> = ({
} else { } else {
questionTypeComponent = ( questionTypeComponent = (
<NumericalQuestion <NumericalQuestion
questionTitle={question.title} questionContent={question.stem}
questionContent={question.stem.text}
correctAnswers={question.choices[0].text} correctAnswers={question.choices[0].text}
handleOnSubmitAnswer={handleOnSubmitAnswer} handleOnSubmitAnswer={handleOnSubmitAnswer}
showAnswer={showAnswer} showAnswer={showAnswer}
@ -81,8 +77,7 @@ const Question: React.FC<QuestionProps> = ({
case 'Short': case 'Short':
questionTypeComponent = ( questionTypeComponent = (
<ShortAnswerQuestion <ShortAnswerQuestion
questionTitle={question.title} questionContent={question.stem}
questionContent={question.stem.text}
choices={question.choices} choices={question.choices}
handleOnSubmitAnswer={handleOnSubmitAnswer} handleOnSubmitAnswer={handleOnSubmitAnswer}
showAnswer={showAnswer} showAnswer={showAnswer}

View file

@ -1,8 +1,9 @@
// ShortAnswerQuestion.tsx // ShortAnswerQuestion.tsx
import React, { useState } from 'react'; import React, { useState } from 'react';
import Latex from 'react-latex';
import '../questionStyle.css'; import '../questionStyle.css';
import { Button, TextField } from '@mui/material'; import { Button, TextField } from '@mui/material';
import TextType from '../../GiftTemplate/templates/TextType';
import { TextFormat } from '../../GiftTemplate/templates/types';
type Choices = { type Choices = {
feedback: { format: string; text: string } | null; feedback: { format: string; text: string } | null;
@ -12,8 +13,7 @@ type Choices = {
}; };
interface Props { interface Props {
questionTitle: string | null; questionContent: TextFormat;
questionContent: string;
choices: Choices[]; choices: Choices[];
globalFeedback?: string | undefined; globalFeedback?: string | undefined;
handleOnSubmitAnswer?: (answer: string) => void; handleOnSubmitAnswer?: (answer: string) => void;
@ -21,16 +21,13 @@ interface Props {
} }
const ShortAnswerQuestion: React.FC<Props> = (props) => { const ShortAnswerQuestion: React.FC<Props> = (props) => {
const { questionTitle, questionContent, choices, showAnswer, handleOnSubmitAnswer, globalFeedback } = props; const { questionContent, choices, showAnswer, handleOnSubmitAnswer, globalFeedback } = props;
const [answer, setAnswer] = useState<string>(); const [answer, setAnswer] = useState<string>();
return ( return (
<div className="question-wrapper"> <div className="question-wrapper">
<div className="title mb-1 text-center center-h-align">
{questionTitle}
</div>
<div className="question content"> <div className="question content">
<Latex>{questionContent}</Latex> <div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
</div> </div>
{showAnswer ? ( {showAnswer ? (
<> <>
@ -46,8 +43,8 @@ const ShortAnswerQuestion: React.FC<Props> = (props) => {
<div className="answer-wrapper mb-1"> <div className="answer-wrapper mb-1">
<TextField <TextField
type="text" type="text"
id={questionContent} id={questionContent.text}
name={questionContent} name={questionContent.text}
onChange={(e) => { onChange={(e) => {
setAnswer(e.target.value); setAnswer(e.target.value);
}} }}

View file

@ -1,12 +1,12 @@
// TrueFalseQuestion.tsx // TrueFalseQuestion.tsx
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import Latex from 'react-latex';
import '../questionStyle.css'; import '../questionStyle.css';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import TextType from '../../GiftTemplate/templates/TextType';
import { TextFormat } from '../../GiftTemplate/templates/types';
interface Props { interface Props {
questionTitle: string | null; questionContent: TextFormat;
questionContent: string;
correctAnswer: boolean; correctAnswer: boolean;
globalFeedback?: string | undefined; globalFeedback?: string | undefined;
handleOnSubmitAnswer?: (answer: boolean) => void; handleOnSubmitAnswer?: (answer: boolean) => void;
@ -14,23 +14,20 @@ interface Props {
} }
const TrueFalseQuestion: React.FC<Props> = (props) => { const TrueFalseQuestion: React.FC<Props> = (props) => {
const { questionTitle, questionContent, correctAnswer, showAnswer, handleOnSubmitAnswer, globalFeedback } = const { questionContent, correctAnswer, showAnswer, handleOnSubmitAnswer, globalFeedback } =
props; props;
const [answer, setAnswer] = useState<boolean | undefined>(undefined); const [answer, setAnswer] = useState<boolean | undefined>(undefined);
useEffect(() => { useEffect(() => {
setAnswer(undefined); setAnswer(undefined);
}, [questionTitle]); }, [questionContent]);
const selectedTrue = answer ? 'selected' : ''; const selectedTrue = answer ? 'selected' : '';
const selectedFalse = answer !== undefined && !answer ? 'selected' : ''; const selectedFalse = answer !== undefined && !answer ? 'selected' : '';
return ( return (
<div className="question-container"> <div className="question-container">
<div className="title mb-1">
{questionTitle}
</div>
<div className="question content"> <div className="question content">
<Latex>{questionContent}</Latex> <div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
</div> </div>
<div className="choices-wrapper mb-1"> <div className="choices-wrapper mb-1">
<Button <Button