diff --git a/tools/challenge-parser/parser/__fixtures__/ast-fill-in-the-blank-many-blanks.json b/tools/challenge-parser/parser/__fixtures__/ast-fill-in-the-blank-many-blanks.json new file mode 100644 index 00000000000..18906722921 --- /dev/null +++ b/tools/challenge-parser/parser/__fixtures__/ast-fill-in-the-blank-many-blanks.json @@ -0,0 +1,272 @@ +{ + "type": "root", + "children": [ + { + "type": "heading", + "depth": 1, + "children": [ + { + "type": "text", + "value": "--fillInTheBlank--", + "position": { + "start": { "line": 1, "column": 3, "offset": 2 }, + "end": { "line": 1, "column": 21, "offset": 20 } + } + } + ], + "position": { + "start": { "line": 1, "column": 1, "offset": 0 }, + "end": { "line": 1, "column": 21, "offset": 20 } + } + }, + { + "type": "heading", + "depth": 2, + "children": [ + { + "type": "text", + "value": "--sentence--", + "position": { + "start": { "line": 3, "column": 4, "offset": 25 }, + "end": { "line": 3, "column": 16, "offset": 37 } + } + } + ], + "position": { + "start": { "line": 3, "column": 1, "offset": 22 }, + "end": { "line": 3, "column": 16, "offset": 37 } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "Sure thing! _ _ _.", + "position": { + "start": { "line": 5, "column": 1, "offset": 39 }, + "end": { "line": 5, "column": 21, "offset": 59 } + } + } + ], + "position": { + "start": { "line": 5, "column": 1, "offset": 39 }, + "end": { "line": 5, "column": 21, "offset": 59 } + } + }, + { + "type": "heading", + "depth": 2, + "children": [ + { + "type": "text", + "value": "--blanks--", + "position": { + "start": { "line": 7, "column": 4, "offset": 64 }, + "end": { "line": 7, "column": 14, "offset": 74 } + } + } + ], + "position": { + "start": { "line": 7, "column": 1, "offset": 61 }, + "end": { "line": 7, "column": 14, "offset": 74 } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "I'd", + "position": { + "start": { "line": 9, "column": 1, "offset": 76 }, + "end": { "line": 9, "column": 6, "offset": 81 } + } + } + ], + "position": { + "start": { "line": 9, "column": 1, "offset": 76 }, + "end": { "line": 9, "column": 6, "offset": 81 } + } + }, + { + "type": "heading", + "depth": 3, + "children": [ + { + "type": "text", + "value": "--feedback--", + "position": { + "start": { "line": 11, "column": 5, "offset": 87 }, + "end": { "line": 11, "column": 17, "offset": 99 } + } + } + ], + "position": { + "start": { "line": 11, "column": 1, "offset": 83 }, + "end": { "line": 11, "column": 17, "offset": 99 } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Feedback 1", + "position": { + "start": { "line": 13, "column": 1, "offset": 101 }, + "end": { "line": 13, "column": 11, "offset": 111 } + } + } + ], + "position": { + "start": { "line": 13, "column": 1, "offset": 101 }, + "end": { "line": 13, "column": 11, "offset": 111 } + } + }, + { + "type": "heading", + "depth": 2, + "children": [ + { + "type": "text", + "value": "--blanks--", + "position": { + "start": { "line": 15, "column": 4, "offset": 116 }, + "end": { "line": 15, "column": 14, "offset": 126 } + } + } + ], + "position": { + "start": { "line": 15, "column": 1, "offset": 113 }, + "end": { "line": 15, "column": 14, "offset": 126 } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "love", + "position": { + "start": { "line": 17, "column": 1, "offset": 128 }, + "end": { "line": 17, "column": 7, "offset": 134 } + } + } + ], + "position": { + "start": { "line": 17, "column": 1, "offset": 128 }, + "end": { "line": 17, "column": 7, "offset": 134 } + } + }, + { + "type": "heading", + "depth": 3, + "children": [ + { + "type": "text", + "value": "--feedback--", + "position": { + "start": { "line": 19, "column": 5, "offset": 140 }, + "end": { "line": 19, "column": 17, "offset": 152 } + } + } + ], + "position": { + "start": { "line": 19, "column": 1, "offset": 136 }, + "end": { "line": 19, "column": 17, "offset": 152 } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Feedback 2", + "position": { + "start": { "line": 21, "column": 1, "offset": 154 }, + "end": { "line": 21, "column": 11, "offset": 164 } + } + } + ], + "position": { + "start": { "line": 21, "column": 1, "offset": 154 }, + "end": { "line": 21, "column": 11, "offset": 164 } + } + }, + { + "type": "heading", + "depth": 2, + "children": [ + { + "type": "text", + "value": "--blanks--", + "position": { + "start": { "line": 23, "column": 4, "offset": 169 }, + "end": { "line": 23, "column": 14, "offset": 179 } + } + } + ], + "position": { + "start": { "line": 23, "column": 1, "offset": 166 }, + "end": { "line": 23, "column": 14, "offset": 179 } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "to", + "position": { + "start": { "line": 25, "column": 1, "offset": 181 }, + "end": { "line": 25, "column": 5, "offset": 185 } + } + } + ], + "position": { + "start": { "line": 25, "column": 1, "offset": 181 }, + "end": { "line": 25, "column": 5, "offset": 185 } + } + }, + { + "type": "heading", + "depth": 3, + "children": [ + { + "type": "text", + "value": "--feedback--", + "position": { + "start": { "line": 27, "column": 5, "offset": 191 }, + "end": { "line": 27, "column": 17, "offset": 203 } + } + } + ], + "position": { + "start": { "line": 27, "column": 1, "offset": 187 }, + "end": { "line": 27, "column": 17, "offset": 203 } + } + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Feedback 3", + "position": { + "start": { "line": 29, "column": 1, "offset": 205 }, + "end": { "line": 29, "column": 11, "offset": 215 } + } + } + ], + "position": { + "start": { "line": 29, "column": 1, "offset": 205 }, + "end": { "line": 29, "column": 11, "offset": 215 } + } + } + ], + "position": { + "start": { "line": 1, "column": 1, "offset": 0 }, + "end": { "line": 30, "column": 1, "offset": 216 } + } +} diff --git a/tools/challenge-parser/parser/__fixtures__/with-fill-in-the-blank-many-blanks.md b/tools/challenge-parser/parser/__fixtures__/with-fill-in-the-blank-many-blanks.md new file mode 100644 index 00000000000..571000bf9c7 --- /dev/null +++ b/tools/challenge-parser/parser/__fixtures__/with-fill-in-the-blank-many-blanks.md @@ -0,0 +1,29 @@ +# --fillInTheBlank-- + +## --sentence-- + +`Sure thing! _ _ _.` + +## --blanks-- + +`I'd` + +### --feedback-- + +Feedback 1 + +## --blanks-- + +`love` + +### --feedback-- + +Feedback 2 + +## --blanks-- + +`to` + +### --feedback-- + +Feedback 3 diff --git a/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.js b/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.js index e3be3f0e9cd..74401fc9d52 100644 --- a/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.js +++ b/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.js @@ -1,5 +1,6 @@ const { root } = require('mdast-builder'); const find = require('unist-util-find'); +const visit = require('unist-util-visit'); const getAllBetween = require('./utils/between-headings'); const getAllBefore = require('./utils/before-heading'); const mdastToHtml = require('./utils/mdast-to-html'); @@ -39,6 +40,8 @@ function plugin() { if (fillInTheBlankNodes.length > 0) { const fillInTheBlankTree = root(fillInTheBlankNodes); + validateBlanksCount(fillInTheBlankTree); + const sentenceNodes = getAllBetween(fillInTheBlankTree, '--sentence--'); const blanksNodes = getAllBetween(fillInTheBlankTree, '--blanks--'); @@ -49,6 +52,18 @@ function plugin() { } } +function validateBlanksCount(fillInTheBlankTree) { + let blanksCount = 0; + visit(fillInTheBlankTree, { value: '--blanks--' }, () => { + blanksCount++; + }); + + if (blanksCount !== 1) + throw Error( + `There should only be one --blanks-- section in the fillInTheBlank challenge` + ); +} + function getfillInTheBlank(sentenceNodes, blanksNodes) { const sentenceWithoutCodeBlocks = sentenceNodes.map(node => { node.children.forEach(child => { diff --git a/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.test.js b/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.test.js index 3a362cf6a34..3246a85ba29 100644 --- a/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.test.js +++ b/tools/challenge-parser/parser/plugins/add-fill-in-the-blank.test.js @@ -3,6 +3,7 @@ const mockFillInTheBlankYouAreAST = require('../__fixtures__/ast-fill-in-the-bla const mockFillInTheBlankTwoSentencesAST = require('../__fixtures__/ast-fill-in-the-blank-two-sentences.json'); const mockFillInTheBlankBadSentence = require('../__fixtures__/ast-fill-in-the-blank-bad-sentence.json'); const mockFillInTheBlankBadParagraph = require('../__fixtures__/ast-fill-in-the-blank-bad-paragraph.json'); +const mockFillInTheBlankMultipleBlanks = require('../__fixtures__/ast-fill-in-the-blank-many-blanks.json'); const addFillInTheBlankQuestion = require('./add-fill-in-the-blank'); describe('fill-in-the-blanks plugin', () => { @@ -126,6 +127,15 @@ Example of good formatting: ); }); + it('should throw if there are multiple --blanks-- sections', () => { + // TODO: Check if this is too wordy + expect(() => { + plugin(mockFillInTheBlankMultipleBlanks, file); + }).toThrow( + `There should only be one --blanks-- section in the fillInTheBlank challenge` + ); + }); + it('should handle one blank', () => { plugin(mockFillInTheBlankYouAreAST, file); const testObject = file.data.fillInTheBlank;