testownik-converter 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testownik-converter",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A command-line utility to convert quizzes into Solvro's Testownik format.",
5
5
  "type": "module",
6
6
  "author": "Konrad Guzek",
@@ -3,47 +3,40 @@ import type { TestownikQuestion, TestownikAnswer } from "@/types";
3
3
  import { BaseAdapter } from "./base-adapter";
4
4
  import { logger } from "@/logging";
5
5
 
6
- const QUESTION_REGEX = new RegExp(
7
- String.raw`^(?:(?<number>\d+)\.\s+)(?<question>[\s\S]+?)$\n(?<answers>(?:^- .+(?:\n(?!- ).+)*\n?)+)`,
8
- "gm",
9
- );
6
+ const QUESTION_REGEX =
7
+ /^(?<number>\d+)\.\s+(?<question>[\s\S]+?)\n^-\s+(?<answers>.+(?:\r?\n.+)+)/gm;
10
8
 
11
- const ANSWER_REGEX = new RegExp(
12
- String.raw`^- (?<correct>\[✓\] )?(?<answer>.+)$`,
13
- "gm",
14
- );
9
+ const ANSWER_REGEX = /^(?<correct>\[✓\]\s+)?(?<answer>[\s\S]+)/m;
15
10
 
16
11
  export class CcnaAdapter extends BaseAdapter {
17
12
  convertQuestions() {
18
- QUESTION_REGEX.lastIndex = 0;
19
13
  const questions: TestownikQuestion[] = [];
20
- let questionMatch: RegExpExecArray | null;
21
- while (
22
- (questionMatch = QUESTION_REGEX.exec(this.inputContent)) != null &&
23
- questionMatch.groups != null
24
- ) {
25
- const answers: TestownikAnswer[] = [];
26
- ANSWER_REGEX.lastIndex = 0;
27
-
14
+ for (const questionMatch of this.inputContent.matchAll(QUESTION_REGEX)) {
15
+ if (questionMatch.groups == null) {
16
+ continue;
17
+ }
28
18
  const questionText = questionMatch.groups.question?.trim();
29
19
  if (!questionText) {
30
20
  logger.warn("Skipping question with no text");
31
21
  continue;
32
22
  }
33
23
 
34
- const answersText = questionMatch.groups.answers;
24
+ const answersText = questionMatch.groups.answers?.trim();
35
25
  if (!answersText) {
36
26
  logger.warn(`Skipping question with no answers: '${questionText}'`);
37
27
  continue;
38
28
  }
39
29
 
40
- let answerMatch: RegExpExecArray | null;
41
- while (
42
- (answerMatch = ANSWER_REGEX.exec(answersText)) != null &&
43
- answerMatch.groups != null
44
- ) {
45
- const answerText = answerMatch.groups.answer?.trim();
46
- if (answerText == null) {
30
+ const answers: TestownikAnswer[] = [];
31
+ for (const fullAnswerText of answersText.split(/\r?\n-\s+/)) {
32
+ const answerMatch = fullAnswerText.match(ANSWER_REGEX);
33
+ if (answerMatch?.groups == null) {
34
+ logger.warn(`Skiping invalid answer: ${fullAnswerText}`);
35
+ continue;
36
+ }
37
+ const isCorrect = answerMatch?.groups?.correct != null;
38
+ const answerText = answerMatch.groups?.answer?.trim();
39
+ if (!answerText) {
47
40
  logger.warn(
48
41
  `Skipping answer with no text in question: ${questionText}`,
49
42
  );
@@ -51,7 +44,7 @@ export class CcnaAdapter extends BaseAdapter {
51
44
  }
52
45
  const answer: TestownikAnswer = {
53
46
  text: answerText,
54
- is_correct: answerMatch.groups.correct != null,
47
+ is_correct: isCorrect,
55
48
  };
56
49
  answers.push(answer);
57
50
  }