83 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
const readdirp = require('readdirp-walk');
 | 
						|
const { has, isEmpty, isNumber } = require('lodash');
 | 
						|
const ora = require('ora');
 | 
						|
 | 
						|
const { parseMarkdown } = require('../../challenge-md-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 occured 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);
 | 
						|
}
 |