diff options
author | James Phillpotts <jphillpotts@scottlogic.co.uk> | 2014-04-10 10:29:17 +0100 |
---|---|---|
committer | Aaron O'Mullan <aaron.omullan@friendco.de> | 2014-04-12 01:26:03 -0700 |
commit | b07681a16a291a38fdbdfa3065a747ab26f9a6c9 (patch) | |
tree | ffb07c822518e689e619dc1ac8780f10877f7b7f /lib/parse | |
parent | f6595f51119baca04bf91e619f64518d400e5cae (diff) | |
download | gitbook-b07681a16a291a38fdbdfa3065a747ab26f9a6c9.zip gitbook-b07681a16a291a38fdbdfa3065a747ab26f9a6c9.tar.gz gitbook-b07681a16a291a38fdbdfa3065a747ab26f9a6c9.tar.bz2 |
Quiz with GFM checkbox lists
Diffstat (limited to 'lib/parse')
-rw-r--r-- | lib/parse/lex.js | 21 | ||||
-rw-r--r-- | lib/parse/page.js | 64 | ||||
-rw-r--r-- | lib/parse/renderer.js | 24 |
3 files changed, 82 insertions, 27 deletions
diff --git a/lib/parse/lex.js b/lib/parse/lex.js index b77b844..a9ff1ba 100644 --- a/lib/parse/lex.js +++ b/lib/parse/lex.js @@ -17,6 +17,10 @@ function splitSections(nodes) { }, []).concat([section]); // Add remaining nodes } +function isQuizNode(node) { + return /^[(\[][ x][)\]]/.test(node.text || node); +} + // What is the type of this section function sectionType(nodes, idx) { var codeType = { type: 'code' }; @@ -35,16 +39,13 @@ function sectionType(nodes, idx) { } if (nodes.length > 2) { - var nonBlockquoteNodes = nodes.slice(nodes[0].type === 'paragraph' ? 1 : 0); - nonBlockquoteNodes.splice(_.findIndex(nonBlockquoteNodes, { type: 'blockquote_start' }), - _.findIndex(nonBlockquoteNodes, { type: 'blockquote_end' })); - - if (nonBlockquoteNodes.length === 2) { - if (_.every(nonBlockquoteNodes, { type: 'table' })) { - if (_.every(nonBlockquoteNodes[0].cells, function(row) { - return _.every(row.slice(1), function(cell) { return cell === "( )"; }); - })) { - return 'quiz'; + var potentialQuizNodes = nodes.slice(nodes[0].type === 'paragraph' ? 1 : 0); + if (_.some(potentialQuizNodes, { type: 'blockquote_start' })) { + for (var i = 0; i < potentialQuizNodes.length; i++) { + var node = potentialQuizNodes[i]; + if ((node.type === 'list_item_start' && isQuizNode(potentialQuizNodes[i+1])) || + (node.type === 'table' && _.every(potentialQuizNodes[i].cells[0].slice(1), isQuizNode))){ + return 'quiz' } } } diff --git a/lib/parse/page.js b/lib/parse/page.js index 4e26455..eb118e4 100644 --- a/lib/parse/page.js +++ b/lib/parse/page.js @@ -36,8 +36,12 @@ function render(section, _options) { return marked.parser(section, options); } -function quizNodesTest(node) { - return node.type === 'table' || node.type === 'list'; +function quizQuestion(node) { + if (node.text) { + node.text = node.text.replace(/^([\[(])x([\])])/, "$1 $2"); + } else { + return node.replace(/^([\[(])x([\])])/, "$1 $2"); + } } function parsePage(src, options) { @@ -81,18 +85,58 @@ function parsePage(src, options) { } }; } else if (section.type === 'quiz') { - var nonQuizNodes = _.reject(section, quizNodesTest); - var quizNodes = _.filter(section, quizNodesTest); - var feedback = nonQuizNodes.splice(_.findIndex(nonQuizNodes, { type: 'blockquote_start' }), _.findIndex(nonQuizNodes, { type: 'blockquote_end' })); + var quiz = [], question, foundFeedback = false; + var nonQuizNodes = section[0].type === 'paragraph' && section[1].type !== 'list_start' ? [section[0]] : []; + var quizNodes = section.slice(0); + quizNodes.splice(0, nonQuizNodes.length); + + for (var i = 0; i < quizNodes.length; i++) { + var node = quizNodes[i]; + + if (question && (((node.type === 'list_end' || node.type === 'blockquote_end') && i === quizNodes.length - 1) + || node.type === 'table' || (node.type === 'paragraph' && !foundFeedback))) { + quiz.push({ + base: render(question.questionNodes), + solution: render(question.solutionNodes), + feedback: render(question.feedbackNodes) + }); + } + + if (node.type === 'table' || (node.type === 'paragraph' && !foundFeedback)) { + question = { questionNodes: [], solutionNodes: [], feedbackNodes: [] }; + } + + if (node.type === 'blockquote_start') { + foundFeedback = true; + } else if (node.type === 'blockquote_end') { + foundFeedback = false; + } + + if (node.type === 'table') { + question.solutionNodes.push(_.cloneDeep(node)); + node.cells = node.cells.map(function(row) { + return row.map(quizQuestion); + }); + question.questionNodes.push(node); + } else if (!/blockquote/.test(node.type)) { + if (foundFeedback) { + question.feedbackNodes.push(node); + } else if (node.type === 'paragraph' || node.type === 'text'){ + question.solutionNodes.push(_.cloneDeep(node)); + quizQuestion(node); + question.questionNodes.push(node); + } else { + question.solutionNodes.push(node); + question.questionNodes.push(node); + } + } + } + return { id: section.id, type: section.type, content: render(nonQuizNodes), - quiz: { - base: render([quizNodes[0]]), - solution: render([quizNodes[1]]), - feedback: render(feedback.slice(1, feedback.length - 1)) - } + quiz: quiz }; } diff --git a/lib/parse/renderer.js b/lib/parse/renderer.js index ba543ee..2a72d48 100644 --- a/lib/parse/renderer.js +++ b/lib/parse/renderer.js @@ -91,14 +91,24 @@ GitBookRenderer.prototype.tablerow = function(content) { return GitBookRenderer.super_.prototype.tablerow(content); }; -GitBookRenderer.prototype.tablecell = function(content, flags) { - var radioContent = content; - if (content === "( )") { - radioContent = "<input type='radio' name='quiz-row-" + this.id + "-" + this.quizRowId + "'/>"; - } else if (content === "(x)") { - radioContent = "<input type='radio' name='quiz-row-" + this.id + "-" + this.quizRowId + "' checked/>"; +var fieldRegex = /^([(\[])([ x])[\])]/; +GitBookRenderer.prototype._createCheckboxAndRadios = function(text) { + var match = fieldRegex.exec(text); + if (!match) { + return text; } - return GitBookRenderer.super_.prototype.tablecell(radioContent, flags); + var field = "<input name='quiz-row-" + this.id + "-" + this.quizRowId + "' type='"; + field += match[1] === '(' ? "radio" : "checkbox"; + field += match[2] === 'x' ? "' checked/>" : "'/>"; + return text.replace(fieldRegex, field); +} + +GitBookRenderer.prototype.tablecell = function(content, flags) { + return GitBookRenderer.super_.prototype.tablecell(this._createCheckboxAndRadios(content), flags); +}; + +GitBookRenderer.prototype.listitem = function(text) { + return GitBookRenderer.super_.prototype.listitem(this._createCheckboxAndRadios(text)); }; // Exports |