diff --git a/src/components/documents/ChoiceAnswer/Quiz/index.tsx b/src/components/documents/ChoiceAnswer/Quiz/index.tsx
index f0af7df3f..d6d928d88 100644
--- a/src/components/documents/ChoiceAnswer/Quiz/index.tsx
+++ b/src/components/documents/ChoiceAnswer/Quiz/index.tsx
@@ -20,7 +20,7 @@ interface Props {
randomizeQuestions?: boolean;
scoring?: ScoringFunction;
minPoints?: number;
- numQuestions: number;
+ questionCount: number;
children?: React.ReactNode[];
}
@@ -55,9 +55,9 @@ const Quiz = observer((props: Props) => {
React.useEffect(() => {
if (props.randomizeQuestions && !doc?.data.questionOrder) {
- doc?.updateQuestionOrder(createRandomOrderMap(props.numQuestions));
+ doc?.updateQuestionOrder(createRandomOrderMap(props.questionCount));
}
- }, [props.randomizeQuestions, doc, props.numQuestions]);
+ }, [props.randomizeQuestions, doc, props.questionCount]);
if (!doc) {
return ;
diff --git a/src/models/documents/ChoiceAnswer.ts b/src/models/documents/ChoiceAnswer/index.ts
similarity index 100%
rename from src/models/documents/ChoiceAnswer.ts
rename to src/models/documents/ChoiceAnswer/index.ts
diff --git a/src/plugins/remark-transform-choice-answer/plugin.ts b/src/plugins/remark-transform-choice-answer/plugin.ts
index cff572ec2..71a2d3ff9 100644
--- a/src/plugins/remark-transform-choice-answer/plugin.ts
+++ b/src/plugins/remark-transform-choice-answer/plugin.ts
@@ -1,8 +1,10 @@
import { visit } from 'unist-util-visit';
-import type { Plugin } from 'unified';
+import type { Plugin, Transformer } from 'unified';
import type { Root, BlockContent, DefinitionContent } from 'mdast';
import type { MdxJsxAttribute, MdxJsxFlowElement } from 'mdast-util-mdx';
-import { toMdxJsxExpressionAttribute } from '../helpers';
+import { toJsxAttribute, toMdxJsxExpressionAttribute } from '../helpers';
+import path from 'path';
+import { promises as fs } from 'fs';
enum ChoiceComponentTypes {
ChoiceAnswer = 'ChoiceAnswer',
@@ -127,6 +129,7 @@ const transformQuestions = (questionNodes: MdxJsxFlowElement[]) => {
const transformQuiz = (quizNode: MdxJsxFlowElement) => {
const questions = [] as MdxJsxFlowElement[];
+
visit(quizNode, 'mdxJsxFlowElement', (childNode) => {
if (Object.values(ChoiceComponentTypes).includes(childNode.name as ChoiceComponentTypes)) {
questions.push(childNode);
@@ -134,17 +137,11 @@ const transformQuiz = (quizNode: MdxJsxFlowElement) => {
});
transformQuestions(questions);
- quizNode.attributes.push(
- toMdxJsxExpressionAttribute('numQuestions', true, {
- type: 'Literal',
- value: questions.length,
- raw: `${questions.length}`
- })
- );
+ quizNode.attributes.push(toJsxAttribute('questionCount', questions.length));
};
-const plugin: Plugin<[], Root> = function choiceAnswerWrapPlugin() {
- return (tree) => {
+const plugin: Plugin<[], Root> = function choiceAnswerWrapPlugin(this, options = []): Transformer {
+ return async (tree, vfile) => {
visit(tree, 'mdxJsxFlowElement', (node) => {
if (node.name === QUIZ_NODE_NAME) {
// Enumerate and transform questions inside the quiz.
diff --git a/src/plugins/remark-transform-choice-answer/tests/artifacts/.gitkeep b/src/plugins/remark-transform-choice-answer/tests/artifacts/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/plugins/remark-transform-choice-answer/tests/plugin.test.ts b/src/plugins/remark-transform-choice-answer/tests/plugin.test.ts
new file mode 100644
index 000000000..ab4352b74
--- /dev/null
+++ b/src/plugins/remark-transform-choice-answer/tests/plugin.test.ts
@@ -0,0 +1,117 @@
+import { remark } from 'remark';
+import remarkMdx from 'remark-mdx';
+import { VFile } from 'vfile';
+import { fileURLToPath } from 'url';
+import { afterEach, describe, expect, it } from 'vitest';
+import path from 'path';
+import { promises as fs } from 'fs';
+
+const __filename = fileURLToPath(import.meta.url);
+
+const alignLeft = (content: string) => {
+ return content
+ .split('\n')
+ .map((line) => line.trimStart())
+ .join('\n');
+};
+
+const process = async (content: string) => {
+ const { default: plugin } = await import('../plugin');
+ const tmpFile = path.resolve(path.dirname(__filename), 'artifacts', `test-${Date.now()}.mdx`);
+ await fs.writeFile(tmpFile, alignLeft(content));
+ const file = new VFile({ value: alignLeft(content), history: [tmpFile] });
+ const result = await remark().use(remarkMdx).use(plugin).process(file);
+
+ return result.value;
+};
+
+afterEach(() => {
+ // clear ./artifacts folder content
+ const artifactsDir = path.resolve(path.dirname(__filename), 'artifacts');
+ fs.readdir(artifactsDir)
+ .then((files) => {
+ const unlinkPromises = files.map((file) =>
+ file !== '.gitkeep' ? fs.unlink(path.join(artifactsDir, file)) : Promise.resolve()
+ );
+ return Promise.all(unlinkPromises);
+ })
+ .catch((err) => {
+ console.warn('Could not clear artifacts directory', err);
+ });
+});
+
+describe('#quiz', () => {
+ it("does nothing if there's no quiz", async () => {
+ const input = `# Heading
+
+ Some content
+ `;
+ const result = await process(input);
+ expect(result).toBe(alignLeft(input));
+ });
+ it('handles empty quiz', async () => {
+ const input = `# Heading
+
+
+
+ `;
+ const result = await process(input);
+ expect(result).toMatchInlineSnapshot(`
+ "# Heading
+
+
+ "
+ `);
+ });
+ it('handles quiz with questions', async () => {
+ const input = `# Heading
+
+
+
+ > In welchem Jahr war 2024?
+
+ 1. 1965
+ 2. 1983
+ 3. 1991
+ 4. 2000
+ 5. 2024
+
+
+ `;
+ const result = await process(input);
+ expect(result).toMatchInlineSnapshot(`
+ "# Heading
+
+
+
+
+ > In welchem Jahr war 2024?
+
+
+
+
+ 1965
+
+
+
+ 1983
+
+
+
+ 1991
+
+
+
+ 2000
+
+
+
+ 2024
+
+
+
+
+ "
+ `);
+ });
+});