summaryrefslogtreecommitdiffstats
path: root/lib/parse/is_quiz.js
diff options
context:
space:
mode:
authorAaron O'Mullan <aaron.omullan@gmail.com>2014-10-13 15:55:32 +0200
committerAaron O'Mullan <aaron.omullan@gmail.com>2014-10-13 15:55:32 +0200
commitc9ec911d0eab7296a808e12470abe90bf764cd6a (patch)
tree187c8af2fb58bb6a641f6c0639966dfefc1ada5b /lib/parse/is_quiz.js
parent32a64be407e05b6ce4275e6f3f9213e8f87f884a (diff)
parent84d7662fd8a2d1abfd0feb92f54064e5d9b9d072 (diff)
downloadgitbook-c9ec911d0eab7296a808e12470abe90bf764cd6a.zip
gitbook-c9ec911d0eab7296a808e12470abe90bf764cd6a.tar.gz
gitbook-c9ec911d0eab7296a808e12470abe90bf764cd6a.tar.bz2
Merge pull request #472 from GitbookIO/fix/quizzes
Fix/quizzes
Diffstat (limited to 'lib/parse/is_quiz.js')
-rw-r--r--lib/parse/is_quiz.js87
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/parse/is_quiz.js b/lib/parse/is_quiz.js
new file mode 100644
index 0000000..3322ff0
--- /dev/null
+++ b/lib/parse/is_quiz.js
@@ -0,0 +1,87 @@
+var _ = require('lodash');
+
+function isQuizNode(node) {
+ return (/^[(\[][ x][)\]]/).test(node.text || node);
+}
+
+function isTableQuestion(nodes) {
+ var block = questionBlock(nodes);
+ return (
+ block.length === 1 &&
+ block[0].type === 'table' &&
+ _.all(block[0].cells[0].slice(1), isQuizNode)
+ );
+}
+
+function isListQuestion(nodes) {
+ var block = questionBlock(nodes);
+ // Counter of when we go in and out of lists
+ var inlist = 0;
+ // Number of lists we found
+ var lists = 0;
+ // Elements found outside a list
+ var outsiders = 0;
+ // Ensure that we have nothing except lists
+ _.each(block, function(node) {
+ if(node.type === 'list_start') {
+ inlist++;
+ } else if(node.type === 'list_end') {
+ inlist--;
+ lists++;
+ } else if(inlist === 0) {
+ // Found non list_start or list_end whilst outside a list
+ outsiders++;
+ }
+ });
+ return lists > 0 && outsiders === 0;
+}
+
+function isQuestion(nodes) {
+ return isListQuestion(nodes) || isTableQuestion(nodes);
+}
+
+// Remove (optional) paragraph header node and blockquote
+function questionBlock(nodes) {
+ return nodes.slice(
+ nodes[0].type === 'paragraph' ? 1 : 0,
+ _.findIndex(nodes, { type: 'blockquote_start' })
+ );
+}
+
+function splitQuestions(nodes) {
+ // Represents nodes in current question
+ var buffer = [];
+ return _.reduce(nodes, function(accu, node) {
+ // Add node to buffer
+ buffer.push(node);
+
+ // Flush buffer once we hit the end of a question
+ if(node.type === 'blockquote_end') {
+ accu.push(buffer);
+ // Clear buffer
+ buffer = [];
+ }
+
+ return accu;
+ }, []);
+}
+
+function isQuiz(nodes) {
+ // Extract potential questions
+ var questions = splitQuestions(
+ // Skip quiz title if there
+ nodes.slice(
+ (nodes[0] && nodes[0].type) === 'paragraph' ? 1 : 0
+ )
+ );
+
+ // Nothing that looks like questions
+ if(questions.length === 0) {
+ return false;
+ }
+
+ // Ensure all questions are correctly structured
+ return _.all(questions, isQuestion);
+}
+
+module.exports = isQuiz;