@@ -6,33 +6,68 @@ import 'package:jaspr/jaspr.dart';
66import 'package:jaspr_content/jaspr_content.dart' ;
77import 'package:yaml/yaml.dart' ;
88
9- import 'models/quiz_model .dart' ;
9+ import '../markdown/markdown_parser .dart' ;
1010import 'client/quiz.dart' ;
11+ import 'models/quiz_model.dart' ;
1112
1213class Quiz extends CustomComponent {
1314 const Quiz () : super .base ();
1415
1516 @override
1617 Component ? create (Node node, NodesBuilder builder) {
17- if (node is ElementNode && node.tag.toLowerCase () == 'quiz' ) {
18- if (node.children? .whereType <ElementNode >().isNotEmpty ?? false ) {
19- throw Exception (
20- 'Invalid Quiz content. Remove any leading empty lines to '
21- 'avoid parsing as markdown.' ,
22- );
23- }
24-
25- final title = node.attributes['title' ];
26-
27- final content = node.children? .map ((n) => n.innerText).join ('\n ' ) ?? '' ;
28- final data = loadYamlNode (content);
29- assert (data is YamlList , 'Invalid Quiz content. Expected a YAML list.' );
30- final questions = (data as YamlList ).nodes
31- .map ((n) => Question .fromMap (n as YamlMap ))
32- .toList ();
33- assert (questions.isNotEmpty, 'Quiz must contain at least one question.' );
34- return InteractiveQuiz (title: title, questions: questions);
18+ if (node is ! ElementNode || node.tag.toLowerCase () != 'quiz' ) {
19+ return null ;
20+ }
21+
22+ final title = node.attributes['title' ];
23+
24+ // If the quiz has an ID, load it from the page data.
25+ if (node.attributes['id' ] case final String quizId when quizId.isNotEmpty) {
26+ return Builder (
27+ builder: (context) {
28+ final quizzes = context.page.data['quiz' ] as Map <String , Object ?>? ;
29+ if (quizzes? [quizId] case final List <Object ?> quizData) {
30+ return InteractiveQuiz (
31+ title: title,
32+ questions: quizData
33+ .map ((q) => _parseQuestion (q as Map <String , Object ?>))
34+ .toList (growable: false ),
35+ );
36+ }
37+
38+ throw ArgumentError ('Failed to parse quiz with ID: $quizId ' );
39+ },
40+ );
3541 }
36- return null ;
42+
43+ // If the quiz does not have an ID, parse it from the content.
44+ if (node.children? .whereType <ElementNode >().isNotEmpty ?? false ) {
45+ throw Exception (
46+ 'Invalid Quiz content. Remove any leading empty lines to '
47+ 'avoid parsing as markdown.' ,
48+ );
49+ }
50+
51+ final content = node.children? .map ((n) => n.innerText).join ('\n ' ) ?? '' ;
52+ final data = loadYamlNode (content);
53+ assert (data is YamlList , 'Invalid Quiz content. Expected a YAML list.' );
54+ final questions = (data as YamlList ).nodes
55+ .map ((n) => Question .fromMap (n as YamlMap ))
56+ .toList ();
57+ assert (questions.isNotEmpty, 'Quiz must contain at least one question.' );
58+ return InteractiveQuiz (title: title, questions: questions);
3759 }
3860}
61+
62+ Question _parseQuestion (Map <Object ?, Object ?> map) => Question (
63+ parseMarkdownToHtml (map['question' ] as String , inline: true ),
64+ (map['options' ] as List <Object ?>)
65+ .map ((e) => _parseAnswer (e as Map <Object ?, Object ?>))
66+ .toList (),
67+ );
68+
69+ AnswerOption _parseAnswer (Map <Object ?, Object ?> map) => AnswerOption (
70+ parseMarkdownToHtml (map['text' ] as String , inline: true ),
71+ map['correct' ] as bool ? ?? false ,
72+ parseMarkdownToHtml (map['explanation' ] as String ),
73+ );
0 commit comments