mirror of https://github.com/FOME-Tech/wiki.git
105 lines
2.9 KiB
JavaScript
105 lines
2.9 KiB
JavaScript
/*
|
|
* usage:
|
|
* note: Windows path separator used below! (to avoid error with parsing of this comment block)
|
|
* " node .\scripts\linkValidator.js 'docs\**\*.md?(x)' "
|
|
*
|
|
* for testing:
|
|
* "node linkValidator.js .\linkValidator.test.md"
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const glob = require('glob');
|
|
|
|
const red = (text) => `\x1b[31m${text}\x1b[0m`;
|
|
|
|
/** @type {Array<{ errType: string, fileName: string, lineContent: string, lineNo: number }>} */
|
|
const errors = [];
|
|
const wikiUrl = 'wiki.fome.tech';
|
|
|
|
/**
|
|
* Check whether links are adhering to custom rules
|
|
* @param {Array<string>} files - List of file names to check
|
|
*/
|
|
const validateDocRules = (files) => {
|
|
if (files.length === 0) {
|
|
console.log('UsageError: no files qualify!');
|
|
process.exit(1);
|
|
}
|
|
|
|
const fileMatchIndicator = files.length > 1 ? `${files.length} files` : files[0];
|
|
|
|
console.log(`Validating rules for URL links in: ${fileMatchIndicator}`);
|
|
|
|
// * Check whether links are not staring with "https://wiki.fome.tech"
|
|
// Note: dynamic javascript string interpolation is used here (see https://www.crstin.com/js-regex-interpolation/)
|
|
const regexPatternDynAbsLink = new RegExp(`\\]\\((https|http):\\/\\/${wikiUrl}`, 'i');
|
|
// hint: test static regex via https://regex101.com
|
|
// * Check whether links are not using a "numbered prefix" like "(/01-blah)"
|
|
const regexPatternStatNumPrefix = new RegExp(/\(.*\/\d\d\-.*\)/, 'i');
|
|
// * Check whether links are not markdown links, meaning ending with .md or .mdx like "(/01-blah.md)"
|
|
const regexPatternStatMdLink = new RegExp(/\(.*\.(md|mdx)\)/, 'i');
|
|
|
|
files.forEach((fileName) => {
|
|
const lines = fs.readFileSync(fileName, 'utf8').split('\n');
|
|
|
|
lines.forEach((line) => {
|
|
if (regexPatternDynAbsLink.test(line)) {
|
|
errors.push({
|
|
errType: 'AbsLink',
|
|
fileName,
|
|
lineContent: line,
|
|
lineNo: lines.indexOf(line) + 1,
|
|
});
|
|
}
|
|
if (regexPatternStatMdLink.test(line)) {
|
|
errors.push({
|
|
errType: 'MdLink',
|
|
fileName,
|
|
lineContent: line,
|
|
lineNo: lines.indexOf(line) + 1,
|
|
});
|
|
}
|
|
if (regexPatternStatNumPrefix.test(line)) {
|
|
errors.push({
|
|
errType: 'NumPrefix',
|
|
fileName,
|
|
lineContent: line,
|
|
lineNo: lines.indexOf(line) + 1,
|
|
});
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Load all md and mdx files from / docs and process them
|
|
*/
|
|
const main = () => {
|
|
// TODO: add try + catch?
|
|
const args = process.argv.slice(2);
|
|
const files = glob.sync(args[0]);
|
|
|
|
// process
|
|
validateDocRules(files);
|
|
|
|
if (errors.length === 0) {
|
|
console.log('✅ Ok');
|
|
process.exit(0);
|
|
}
|
|
|
|
console.log('❌ Failed\n');
|
|
console.log(red(`Number of Errors found: ${errors.length}`));
|
|
errors.forEach((error) => {
|
|
console.log(
|
|
`[${error.fileName}][Line:${error.lineNo}][Type:${
|
|
error.errType
|
|
}]" ${error.lineContent.trim()}"`,
|
|
);
|
|
});
|
|
|
|
process.exit(2);
|
|
};
|
|
|
|
// main
|
|
main();
|