in scripts/link-checker.js [27:137]
files: scanFolder(p),
path: p,
project: project.name,
});
});
});
},
},
{
title: 'Scan all links',
task: (ctx) => {
ctx.externalLinks = []; // links to other sites
ctx.internalLinks = []; // links to other Markdown files or anchor
ctx.allDocuments.forEach((documents) => {
documents.files.forEach((file) => {
const scanResult = scanLinkInMDFile(file, documents.project);
ctx.externalLinks.push(...scanResult.links);
ctx.internalLinks.push(...scanResult.filteredLinks);
});
});
console.log(`[Link Scanner] Scan result: ${ctx.externalLinks.length} external links, ${ctx.internalLinks.length} internal links`);
},
},
{
title: 'Start external link check',
task: async (ctx) => {
ctx.externalBrokenList = [];
const externalLinkCheckPromises = [];
ctx.externalLinks.forEach((link) => {
externalLinkCheckPromises.push(linkValidate(link));
});
const result = await Promise.all(externalLinkCheckPromises);
ctx.externalBrokenList.push(...result.filter((item) => item.status !== 200));
},
},
{
title: 'Start internal link check',
task: (ctx) => {
ctx.internalBrokenList = [];
ctx.internalLinks.forEach((link) => {
if (!fs.existsSync(link.url)) {
ctx.internalBrokenList.push(link);
}
});
},
},
{
title: 'Write broken list to file',
task: (ctx) => {
fs.writeFileSync('./brokenLinks.json', JSON.stringify({
external: ctx.externalBrokenList,
internal: ctx.internalBrokenList,
}));
},
},
]);
tasks.run()
.then(() => {
console.log('[Finish] Link Checker finished');
})
.catch((err) => {
console.error(err);
process.exit(1);
});
function scanFolder(tarDir) {
const filePaths = [];
const files = fs.readdirSync(tarDir);
files.forEach((file) => {
const tarPath = path.join(tarDir, file);
const stats = fs.statSync(tarPath);
if (stats.isDirectory()) {
filePaths.push(...scanFolder(tarPath));
} else {
filePaths.push(tarPath);
}
});
return filePaths;
}
function scanLinkInMDFile(filePath, project) {
const fileContent = fs.readFileSync(filePath, 'utf-8');
const regex = /\[[\s\S]*?\]\([\s\S]*?\)/g;
if (fileContent.match(regex)) {
const arrayOfLinks = fileContent.match(regex);
const links = arrayOfLinks.map((item) => {
const textHrefDivide = item.split('](');
const text = textHrefDivide[0].replace('[', '');
const url = textHrefDivide[1].replace(')', '');
return ({ url, text, file: filePath });
});
// filter out links to other Markdown files
const filteredList = []; // local files
const unfilteredList = links.filter((link) => { // web links
let url = link.url.trim();
if (url.startsWith('http://') || url.startsWith('https://')) {
// eslint-disable-next-line no-param-reassign
link.url = url;
return true;
}
// url preprocess
if (url.startsWith('#') || url.indexOf('#') > 0) { // such as "#abcd"
const split = url.split('#').filter((item) => item !== '');
if (split.length > 1) {