mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-31 15:03:21 -05:00
96 lines
2.9 KiB
JavaScript
96 lines
2.9 KiB
JavaScript
const { root } = require('mdast-builder');
|
|
const find = require('unist-util-find');
|
|
const { getSection } = require('./utils/get-section');
|
|
const getAllBefore = require('./utils/before-heading');
|
|
const mdastToHtml = require('./utils/mdast-to-html');
|
|
const { getParagraphContent } = require('./utils/get-paragraph-content');
|
|
|
|
const { splitOnThematicBreak } = require('./utils/split-on-thematic-break');
|
|
|
|
function plugin() {
|
|
return transformer;
|
|
function transformer(tree, file) {
|
|
const allQuestionNodes = getSection(tree, '--questions--');
|
|
|
|
if (allQuestionNodes.length > 0) {
|
|
const questions = [];
|
|
const questionTrees = [];
|
|
|
|
allQuestionNodes.forEach(questionNode => {
|
|
const isStartOfQuestion =
|
|
questionNode.children?.[0]?.value === '--text--';
|
|
if (isStartOfQuestion) {
|
|
questionTrees.push([questionNode]);
|
|
} else {
|
|
questionTrees[questionTrees.length - 1].push(questionNode);
|
|
}
|
|
});
|
|
|
|
questionTrees.forEach(questionNodes => {
|
|
const questionTree = root(questionNodes);
|
|
|
|
const textNodes = getSection(questionTree, '--text--');
|
|
const answersNodes = getSection(questionTree, '--answers--');
|
|
const solutionNodes = getSection(questionTree, '--video-solution--');
|
|
|
|
questions.push(getQuestion(textNodes, answersNodes, solutionNodes));
|
|
});
|
|
|
|
file.data.questions = questions;
|
|
}
|
|
}
|
|
}
|
|
|
|
function getQuestion(textNodes, answersNodes, solutionNodes) {
|
|
const text = mdastToHtml(textNodes);
|
|
const answers = getAnswers(answersNodes);
|
|
const solution = getSolution(solutionNodes);
|
|
|
|
if (!text) throw Error('text is missing from question');
|
|
if (!answers) throw Error('answers are missing from question');
|
|
if (!solution) throw Error('solution is missing from question');
|
|
|
|
return { text, answers, solution };
|
|
}
|
|
|
|
function getAnswers(answersNodes) {
|
|
const answerGroups = splitOnThematicBreak(answersNodes);
|
|
|
|
return answerGroups.map(answerGroup => {
|
|
const answerTree = root(answerGroup);
|
|
const feedback = find(answerTree, { value: '--feedback--' });
|
|
|
|
if (feedback) {
|
|
const answerNodes = getAllBefore(answerTree, '--feedback--');
|
|
const feedbackNodes = getSection(answerTree, '--feedback--');
|
|
|
|
if (answerNodes.length < 1) {
|
|
throw Error('Answer missing');
|
|
}
|
|
|
|
return {
|
|
answer: mdastToHtml(answerNodes),
|
|
feedback: mdastToHtml(feedbackNodes)
|
|
};
|
|
}
|
|
|
|
return { answer: mdastToHtml(answerGroup), feedback: null };
|
|
});
|
|
}
|
|
|
|
function getSolution(solutionNodes) {
|
|
let solution;
|
|
try {
|
|
solution = Number(getParagraphContent(solutionNodes[0]));
|
|
if (Number.isNaN(solution)) throw Error('Not a number');
|
|
if (solution < 1) throw Error('Not positive number');
|
|
} catch (e) {
|
|
console.log(e);
|
|
throw Error('A video solution should be a positive integer');
|
|
}
|
|
|
|
return solution;
|
|
}
|
|
|
|
module.exports = plugin;
|