-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
99 lines (72 loc) · 1.94 KB
/
index.js
File metadata and controls
99 lines (72 loc) · 1.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import * as ohm from 'ohm-js';
export const grammar = ohm.grammar(String.raw`
QuizMarkdown {
Quiz = Block+
Block = Question Answers
Question = text
Answers = Answer+
Answer = "-" "[" mark? "]" text
mark = " " | "x"
text = (~eol any)+ (eol | end)
eol = "\r"? "\n"
}
`);
function map_schema(list) {
return list.children.map(child => child.schema());
}
export const semantics = grammar.createSemantics().addOperation('schema', {
Quiz(blocks) {
return {
"@context": "https://schema.org/",
"@type": "Quiz",
"hasPart": map_schema(blocks)
};
},
Block(question, answers) {
return {
...question.schema(),
...answers.schema()
}
},
Question(text) {
return {
"@type": "Question",
text: text.schema()
}
},
Answers(answers) {
const [correct, wrong] =
map_schema(answers).reduce(
([c, w], [status, answer], position) => {
(status ? c : w).push({...answer, position});
return [c, w];
},
[[], []]
);
// Assuming that a question **MUST** have at least one correct answer.
if (correct.length === 0) {
throw new Error("question with no correct answers");
}
return {
acceptedAnswer: correct.length === 1 ? correct[0] : correct,
suggestedAnswer: wrong.length === 1 ? wrong[0] : wrong
};
},
Answer(_, __, mark, ___, text) {
// When `- [ ] Answer A` then `mark` is `[]` (empty)
// When `- [x] Answer B` then `mark` is `[x]`
const correct = mark.children.length === 1;
return [correct, {"@type": "Answer", text: text.schema()}];
},
text(val, _) {
return val.sourceString;
},
});
/**
Takes a markdown document as parameter (`md_string`)
and returns a Quiz JSON-LD structured data document.
*/
export const parse = (md_string) => {
const match = grammar.match(md_string);
return semantics(match).schema();
};