diff --git a/tools/scripts/ci/ensure-challenge-formatting.js b/tools/scripts/ci/ensure-challenge-formatting.js deleted file mode 100644 index 28ff726252..0000000000 --- a/tools/scripts/ci/ensure-challenge-formatting.js +++ /dev/null @@ -1,82 +0,0 @@ -const readdirp = require('readdirp-walk'); -const { has, isEmpty, isNumber } = require('lodash'); -const ora = require('ora'); - -const { parseMarkdown } = require('../../challenge-parser'); -const { challengeRoot, checkFrontmatter } = require('./md-testing-utils'); - -const scrimbaUrlRE = /^https:\/\/scrimba\.com\//; -const requiredProps = ['title', 'id', 'challengeType']; - -const spinner = ora('Checking challenge markdown formatting').start(); - -readdirp({ root: challengeRoot, directoryFilter: '!_meta' }) - .on('data', file => - Promise.all([ - isChallengeParseable(file), - checkFrontmatter(file, { - validator: challengeFrontmatterValidator(file) - }) - ]).catch(err => { - console.info(` - the following error occurred when testing - - ${file.fullPath} - - `); - console.error(err); - // eslint-disable-next-line no-process-exit - process.exit(1); - }) - ) - .on('end', () => spinner.stop()); - -const challengeFrontmatterValidator = file => frontmatter => { - const { fullPath } = file; - - const hasRequiredProperties = requiredProps - .map( - prop => - has(frontmatter, prop) && - (!isEmpty(frontmatter[prop]) || isNumber(frontmatter[prop])) - ) - .every(bool => bool); - - if (!hasRequiredProperties) { - console.log(`${fullPath} is missing required frontmatter - - ${JSON.stringify(frontmatter, null, 2)} - - Required properties are: ${JSON.stringify(requiredProps, null, 2)} - - `); - } - - const { videoUrl } = frontmatter; - let validVideoUrl = false; - if (!isEmpty(videoUrl) && !scrimbaUrlRE.test(videoUrl)) { - validVideoUrl = true; - console.log(` - ${fullPath} contains an invalid videoUrl - `); - } - - const { forumTopicId } = frontmatter; - let validForumTopicId = false; - if (!isEmpty(forumTopicId) && !isNumber(forumTopicId)) { - validForumTopicId = true; - console.log(` - ${fullPath} contains an invalid forumTopicId - `); - } - - return hasRequiredProperties && validVideoUrl && validForumTopicId; -}; - -function isChallengeParseable(file) { - const { stat, fullPath } = file; - if (!stat.isFile() || /_meta/.test(fullPath)) { - return Promise.resolve(true); - } - return parseMarkdown(fullPath); -} diff --git a/tools/scripts/ci/ensure-guide-formatting.js b/tools/scripts/ci/ensure-guide-formatting.js deleted file mode 100644 index a1931550be..0000000000 --- a/tools/scripts/ci/ensure-guide-formatting.js +++ /dev/null @@ -1,34 +0,0 @@ -const readdirp = require('readdirp-walk'); -const { has } = require('lodash'); -const ora = require('ora'); - -const { - guideRoot, - checkGuideFile, - checkFrontmatter, - extractLangFromFileName -} = require('./md-testing-utils'); - -const spinner = ora('Checking guide markdown formatting').start(); - -const guideFrontmatterValidator = file => frontmatter => { - const hasLocale = - extractLangFromFileName(file) === 'english' - ? true - : has(frontmatter, 'localeTitle'); - const hasTitle = has(frontmatter, 'title'); - return hasLocale && hasTitle; -}; - -readdirp({ root: guideRoot }) - .on('data', file => - Promise.all([ - checkGuideFile(file), - checkFrontmatter(file, { validator: guideFrontmatterValidator(file) }) - ]).catch(err => { - console.error(err); - // eslint-disable-next-line no-process-exit - process.exit(1); - }) - ) - .on('end', () => spinner.stop()); diff --git a/tools/scripts/ci/md-testing-utils.js b/tools/scripts/ci/md-testing-utils.js deleted file mode 100644 index 318af50226..0000000000 --- a/tools/scripts/ci/md-testing-utils.js +++ /dev/null @@ -1,117 +0,0 @@ -const path = require('path'); -const fs = require('fs'); -const matter = require('gray-matter'); -const { dasherize } = require('../../../utils/slugs'); - -const pass = true; - -const guideRoot = path.resolve(__dirname, '../../../guide'); -const challengeRoot = path.resolve(__dirname, '../../../curriculum/challenges'); -exports.guideRoot = guideRoot; -exports.challengeRoot = challengeRoot; - -const allowedLangDirNames = [ - 'arabic', - 'chinese', - 'english', - 'portuguese', - 'russian', - 'spanish' -]; - -exports.checkGuideFile = function checkGuideFile(file) { - const { stat, depth, name, fullPath } = file; - if (depth === 1) { - if (stat.isFile()) { - throw new Error(`${name} is not valid in the ${guideRoot} directory`); - } - if (!allowedLangDirNames.includes(name)) { - throw new Error(`${name} should not be in the ${guideRoot} directory`); - } - } - if (stat.isDirectory()) { - return checkDirName(name, fullPath); - } - return checkGuideFileName(name, fullPath); -}; - -function checkDirName(dirName, fullPath) { - return new Promise((resolve, reject) => { - if (dasherize(dirName) !== dirName) { - return reject( - new Error(` -Invalid or upper case character found in '${dirName}', please use '-' for spaces -and all folder names must be lower case. Valid characters are [a-z0-9\\-.]. - - Found in: - ${fullPath} -`) - ); - } - return resolve(pass); - }); -} - -function checkGuideFileName(fileName, fullPath) { - return new Promise((resolve, reject) => { - if (fileName !== 'index.md') { - return reject( - new Error( - `${fileName} is not a valid file name, please use 'index.md' - - Found in: - ${fullPath} - ` - ) - ); - } - return resolve(pass); - }); -} - -exports.checkFrontmatter = function checkFrontmatter( - { fullPath, stat }, - options = { - validator() { - return true; - } - } -) { - if (!stat.isFile()) { - return Promise.resolve(pass); - } - return new Promise((resolve, reject) => - fs.readFile(fullPath, 'utf8', (err, content) => { - if (err) { - return reject(new Error(err)); - } - try { - const { data: frontmatter } = matter(content); - const { validator } = options; - if (!validator(frontmatter)) { - return reject( - new Error( - `The article at: ${fullPath} failed frontmatter validation.` - ) - ); - } - return resolve(pass); - } catch (e) { - console.log(` - - The below occurred in: - - ${fullPath} - - `); - throw e; - } - }) - ); -}; - -function extractLangFromFileName({ path: relativePath }) { - return relativePath.split(path.sep)[0]; -} - -exports.extractLangFromFileName = extractLangFromFileName;