summaryrefslogtreecommitdiffstats
path: root/lib/parse/is_quiz.js
blob: 4a24cfcfb938a67f576c90183630c791797815f3 (plain)
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
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(nodes);

    // Nothing that looks like questions
    if(questions.length === 0) {
        return false;
    }

    // Ensure all questions are correctly structured
    return _.all(questions, isQuestion);
}

module.exports = isQuiz;