From 3104c9e057f22ab237c28190d9ae112419980bf5 Mon Sep 17 00:00:00 2001 From: Anna Date: Tue, 1 Apr 2025 16:32:52 -0400 Subject: [PATCH] feat: test page structure (#59113) Co-authored-by: Naomi Co-authored-by: Oliver Eyton-Williams --- .../parser/__fixtures__/with-subsection.md | 19 +++++++++++ .../parser/plugins/add-text.js | 11 ++++++- .../parser/plugins/add-text.test.js | 13 +++++++- .../parser/plugins/utils/get-section.js | 32 +++++++++---------- 4 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 tools/challenge-parser/parser/__fixtures__/with-subsection.md diff --git a/tools/challenge-parser/parser/__fixtures__/with-subsection.md b/tools/challenge-parser/parser/__fixtures__/with-subsection.md new file mode 100644 index 00000000000..0b982110cbd --- /dev/null +++ b/tools/challenge-parser/parser/__fixtures__/with-subsection.md @@ -0,0 +1,19 @@ +# --description-- + +Paragraph 1 + +```html +code example +``` + +## --not-allowed-- + +should not be allowed + +# --instructions-- + +Paragraph 0 + +```html +code example 0 +``` diff --git a/tools/challenge-parser/parser/plugins/add-text.js b/tools/challenge-parser/parser/plugins/add-text.js index 07922b4dca6..d9bcc4c48f3 100644 --- a/tools/challenge-parser/parser/plugins/add-text.js +++ b/tools/challenge-parser/parser/plugins/add-text.js @@ -1,5 +1,7 @@ const { isEmpty } = require('lodash'); -const { getSection } = require('./utils/get-section'); +const find = require('unist-util-find'); +const { root } = require('mdast-builder'); +const { getSection, isMarker } = require('./utils/get-section'); const mdastToHTML = require('./utils/mdast-to-html'); function addText(sectionIds) { @@ -9,6 +11,13 @@ function addText(sectionIds) { function transformer(tree, file) { for (const sectionId of sectionIds) { const textNodes = getSection(tree, `--${sectionId}--`); + const subSection = find(root(textNodes), isMarker); + if (subSection) { + throw Error( + `The --${sectionId}-- section should not have any subsections. Found subsection ${subSection.children[0].value}` + ); + } + const sectionText = mdastToHTML(textNodes); if (!isEmpty(sectionText)) { diff --git a/tools/challenge-parser/parser/plugins/add-text.test.js b/tools/challenge-parser/parser/plugins/add-text.test.js index 875937eda3f..804c2309859 100644 --- a/tools/challenge-parser/parser/plugins/add-text.test.js +++ b/tools/challenge-parser/parser/plugins/add-text.test.js @@ -2,7 +2,7 @@ const parseFixture = require('../__fixtures__/parse-fixture'); const addText = require('./add-text'); describe('add-text', () => { - let realisticAST, mockAST; + let realisticAST, mockAST, withSubSectionAST; const descriptionId = 'description'; const instructionsId = 'instructions'; const missingId = 'missing'; @@ -11,6 +11,7 @@ describe('add-text', () => { beforeAll(async () => { realisticAST = await parseFixture('realistic.md'); mockAST = await parseFixture('simple.md'); + withSubSectionAST = await parseFixture('with-subsection.md'); }); beforeEach(() => { @@ -43,6 +44,16 @@ describe('add-text', () => { }).toThrow(expectedError); }); + it('throws when there is a sub-section in one of the sections', () => { + const plugin = addText([instructionsId, descriptionId]); + + expect(() => { + plugin(withSubSectionAST, file); + }).toThrow( + 'The --description-- section should not have any subsections. Found subsection --not-allowed--' + ); + }); + it('should add a string relating to the section id to `file.data`', () => { const plugin = addText([descriptionId]); plugin(mockAST, file); diff --git a/tools/challenge-parser/parser/plugins/utils/get-section.js b/tools/challenge-parser/parser/plugins/utils/get-section.js index faf0414b604..326afbc5564 100644 --- a/tools/challenge-parser/parser/plugins/utils/get-section.js +++ b/tools/challenge-parser/parser/plugins/utils/get-section.js @@ -4,27 +4,25 @@ const findAllAfter = require('unist-util-find-all-after'); const between = require('unist-util-find-all-between'); const { findAll } = require('./find-all'); +const isMarker = node => { + if (node.children && node.children[0]) { + const child = node.children[0]; + return ( + child.type === 'text' && + child.value.startsWith('--') && + child.value.endsWith('--') && + node.type === 'heading' + ); + } + return false; +}; + function _getSection(tree) { return start => { if (!start) return []; const isEnd = node => { - return ( - node.type === 'heading' && node.depth <= start.depth && isMarker(node) - ); - }; - - const isMarker = node => { - if (node.children && node.children[0]) { - const child = node.children[0]; - return ( - child.type === 'text' && - child.value.startsWith('--') && - child.value.endsWith('--') - ); - } else { - return false; - } + return node.depth <= start.depth && isMarker(node); }; const end = findAfter(tree, start, isEnd); @@ -56,4 +54,4 @@ function getAllSections(tree, marker) { return starts.map(_getSection(tree)); } -module.exports = { getSection, getAllSections }; +module.exports = { getSection, getAllSections, isMarker };