mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
added escape support on matching text
This commit is contained in:
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
@@ -38,6 +38,9 @@ importers:
|
||||
jsdom:
|
||||
specifier: ^25.0.0
|
||||
version: 25.0.1
|
||||
marked-katex-extension:
|
||||
specifier: ^5.1.4
|
||||
version: 5.1.4(katex@0.16.20)(marked@14.1.4)
|
||||
next:
|
||||
specifier: ^15.0.2
|
||||
version: 15.1.0(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
@@ -1105,6 +1108,10 @@ packages:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
commander@8.3.0:
|
||||
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
@@ -1833,6 +1840,10 @@ packages:
|
||||
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
||||
katex@0.16.20:
|
||||
resolution: {integrity: sha512-jjuLaMGD/7P8jUTpdKhA9IoqnH+yMFB3sdAFtq5QdAqeP2PjiSbnC3EaguKPNtv6dXXanHxp1ckwvF4a86LBig==}
|
||||
hasBin: true
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
@@ -1881,6 +1892,12 @@ packages:
|
||||
magic-string@0.30.17:
|
||||
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
||||
|
||||
marked-katex-extension@5.1.4:
|
||||
resolution: {integrity: sha512-GQOio4vCp0laxB1IY+2oNVo5nbn82yWMDP/jILRYHmyu2WXMVlXCB+krq2/U2fQn+V9j8aqDmnNdrsgqG2AkGQ==}
|
||||
peerDependencies:
|
||||
katex: '>=0.16 <0.17'
|
||||
marked: '>=4 <16'
|
||||
|
||||
marked@14.1.4:
|
||||
resolution: {integrity: sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==}
|
||||
engines: {node: '>= 18'}
|
||||
@@ -3647,6 +3664,8 @@ snapshots:
|
||||
|
||||
commander@4.1.1: {}
|
||||
|
||||
commander@8.3.0: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
convert-source-map@2.0.0: {}
|
||||
@@ -4570,6 +4589,10 @@ snapshots:
|
||||
object.assign: 4.1.5
|
||||
object.values: 1.2.0
|
||||
|
||||
katex@0.16.20:
|
||||
dependencies:
|
||||
commander: 8.3.0
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
@@ -4613,6 +4636,11 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
marked-katex-extension@5.1.4(katex@0.16.20)(marked@14.1.4):
|
||||
dependencies:
|
||||
katex: 0.16.20
|
||||
marked: 14.1.4
|
||||
|
||||
marked@14.1.4: {}
|
||||
|
||||
math-intrinsics@1.0.0: {}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
QuestionType,
|
||||
} from "@/models/local/quiz/localQuizQuestion";
|
||||
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
||||
import { escapeMatchingText } from "@/services/utils/questionHtmlUtils";
|
||||
|
||||
export default function QuizPreview({
|
||||
moduleName,
|
||||
@@ -78,6 +79,8 @@ export default function QuizPreview({
|
||||
|
||||
function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
|
||||
question.answers.map(a => console.log(escapeMatchingText(a.text)))
|
||||
return (
|
||||
<div className="rounded bg-slate-900 px-2">
|
||||
<div className="flex flex-row justify-between text-slate-400">
|
||||
@@ -89,7 +92,9 @@ function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
||||
|
||||
<div
|
||||
className="ms-4 mb-2 markdownPreview"
|
||||
dangerouslySetInnerHTML={{ __html: markdownToHTMLSafe(question.text, settings) }}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: markdownToHTMLSafe(question.text, settings),
|
||||
}}
|
||||
></div>
|
||||
{question.questionType === QuestionType.MATCHING && (
|
||||
<div>
|
||||
@@ -98,8 +103,10 @@ function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
||||
key={JSON.stringify(answer)}
|
||||
className="mx-3 mb-1 bg-dark rounded border border-slate-600 flex flex-row"
|
||||
>
|
||||
<div className="text-right my-auto">{answer.text} - </div>
|
||||
<div className="">{answer.matchedText}</div>
|
||||
<div className="text-right my-auto flex-1 pe-3">
|
||||
{escapeMatchingText(answer.text)}
|
||||
</div>
|
||||
<div className=" flex-1">{answer.matchedText}</div>
|
||||
</div>
|
||||
))}
|
||||
{question.matchDistractors.map((distractor) => (
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
import { QuestionType } from "../localQuizQuestion";
|
||||
import { LocalQuizQuestionAnswer } from "../localQuizQuestionAnswer";
|
||||
|
||||
const parseMatchingAnswer = (input: string) => {
|
||||
const matchingPattern = /^\^?/;
|
||||
const textWithoutMatchDelimiter = input.replace(matchingPattern, "");
|
||||
const [text, ...matchedParts] = textWithoutMatchDelimiter.split(" - ");
|
||||
const answer: LocalQuizQuestionAnswer = {
|
||||
correct: true,
|
||||
text: text.trim(),
|
||||
matchedText: matchedParts.join("-").trim(),
|
||||
};
|
||||
return answer;
|
||||
};
|
||||
|
||||
export const quizQuestionAnswerMarkdownUtils = {
|
||||
// getHtmlText(): string {
|
||||
// return MarkdownService.render(this.text);
|
||||
@@ -10,17 +22,7 @@ export const quizQuestionAnswerMarkdownUtils = {
|
||||
const isCorrect = input.startsWith("*") || input[1] === "*";
|
||||
|
||||
if (questionType === QuestionType.MATCHING) {
|
||||
const matchingPattern = /^\^ ?/;
|
||||
const textWithoutMatchDelimiter = input
|
||||
.replace(matchingPattern, "")
|
||||
.trim();
|
||||
const [text, ...matchedParts] = textWithoutMatchDelimiter.split("-");
|
||||
const answer: LocalQuizQuestionAnswer = {
|
||||
correct: true,
|
||||
text: text.trim(),
|
||||
matchedText: matchedParts.join("-").trim(),
|
||||
};
|
||||
return answer;
|
||||
return parseMatchingAnswer(input);
|
||||
}
|
||||
|
||||
const startingQuestionPattern = /^(\*?[a-z]?\))|\[\s*\]|\[\*\]|\^ /;
|
||||
|
||||
@@ -102,7 +102,11 @@ const getAnswers = (
|
||||
questionIndex: number,
|
||||
questionType: string
|
||||
): LocalQuizQuestionAnswer[] => {
|
||||
if (questionType == QuestionType.SHORT_ANSWER_WITH_ANSWERS) linesWithoutPoints = linesWithoutPoints.slice(0, linesWithoutPoints.length - 1);
|
||||
if (questionType == QuestionType.SHORT_ANSWER_WITH_ANSWERS)
|
||||
linesWithoutPoints = linesWithoutPoints.slice(
|
||||
0,
|
||||
linesWithoutPoints.length - 1
|
||||
);
|
||||
const answerLines = getAnswerStringsWithMultilineSupport(
|
||||
linesWithoutPoints,
|
||||
questionIndex
|
||||
|
||||
@@ -131,4 +131,36 @@ Match the following terms & definitions
|
||||
"^ statement - a single command to be executed\n^ - this is the distractor"
|
||||
);
|
||||
});
|
||||
it("can escape - characters", () => {
|
||||
const name = "Test Quiz"
|
||||
const rawMarkdownQuiz = `
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description:
|
||||
---
|
||||
Match the following terms & definitions
|
||||
|
||||
^ git add \-\-all - start tracking all files in the current directory and subdirectories
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name);
|
||||
|
||||
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.answers[0].text).toBe("git add --all");
|
||||
expect(firstQuestion.answers[0].matchedText).toBe("start tracking all files in the current directory and subdirectories");
|
||||
|
||||
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
|
||||
expect(quizMarkdown).toContain(
|
||||
"^ git add \-\-all - start tracking all files in the current directory and subdirectories"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,16 +11,24 @@ import {
|
||||
} from "@/models/local/quiz/localQuizQuestion";
|
||||
import { CanvasQuizQuestion } from "@/models/canvas/quizzes/canvasQuizQuestionModel";
|
||||
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||
import { escapeMatchingText } from "../utils/questionHtmlUtils";
|
||||
|
||||
|
||||
export const getAnswers = (
|
||||
question: LocalQuizQuestion,
|
||||
settings: LocalCourseSettings
|
||||
) => {
|
||||
if (question.questionType === QuestionType.MATCHING)
|
||||
return question.answers.map((a) => ({
|
||||
answer_match_left: a.text,
|
||||
return question.answers.map((a) => {
|
||||
const text =
|
||||
question.questionType === QuestionType.MATCHING
|
||||
? escapeMatchingText(a.text)
|
||||
: a.text;
|
||||
return {
|
||||
answer_match_left: text,
|
||||
answer_match_right: a.matchedText,
|
||||
}));
|
||||
};
|
||||
});
|
||||
|
||||
return question.answers.map((answer) => ({
|
||||
answer_html: markdownToHTMLSafe(answer.text, settings),
|
||||
@@ -29,11 +37,9 @@ export const getAnswers = (
|
||||
}));
|
||||
};
|
||||
|
||||
export const getQuestionType = (
|
||||
question: LocalQuizQuestion
|
||||
) => {
|
||||
export const getQuestionType = (question: LocalQuizQuestion) => {
|
||||
return `${question.questionType.replace("=", "")}_question`;
|
||||
}
|
||||
};
|
||||
|
||||
const createQuestionOnly = async (
|
||||
canvasCourseId: number,
|
||||
@@ -45,6 +51,7 @@ const createQuestionOnly = async (
|
||||
console.log("Creating individual question"); //, question);
|
||||
|
||||
const url = `${canvasApi}/courses/${canvasCourseId}/quizzes/${canvasQuizId}/questions`;
|
||||
|
||||
const body = {
|
||||
question: {
|
||||
question_text: markdownToHTMLSafe(question.text, settings),
|
||||
@@ -179,7 +186,12 @@ export const canvasQuizService = {
|
||||
};
|
||||
|
||||
const { data: canvasQuiz } = await axiosClient.post<CanvasQuiz>(url, body);
|
||||
await createQuizQuestions(canvasCourseId, canvasQuiz.id, localQuiz, settings);
|
||||
await createQuizQuestions(
|
||||
canvasCourseId,
|
||||
canvasQuiz.id,
|
||||
localQuiz,
|
||||
settings
|
||||
);
|
||||
return canvasQuiz.id;
|
||||
},
|
||||
async delete(canvasCourseId: number, canvasQuizId: number) {
|
||||
|
||||
4
src/services/utils/questionHtmlUtils.ts
Normal file
4
src/services/utils/questionHtmlUtils.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
export function escapeMatchingText(input: string){
|
||||
return input.replaceAll("\\-", "-");
|
||||
}
|
||||
Reference in New Issue
Block a user