nx/scripts/documentation/map-link-checker.ts
2022-07-14 14:17:26 +00:00

124 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Check the integrity of `map.json` file.
* - Error if `map.json` reference a markdown file that does not exist
* - Error if a markdown file exists without reference in `map.json`
*/
import { readJsonSync } from 'fs-extra';
import * as glob from 'glob';
import * as chalk from 'chalk';
console.log(`${chalk.blue('i')} Documentation Map Check`);
const basePath = 'docs';
const sharedFilesPattern = 'shared/cli';
// These are Overview documentation files showed at url like `/packages/:name`
const allowedOrphanFiles: string[] = [
'shared/angular-plugin.md',
'shared/cypress-plugin.md',
'shared/detox-plugin.md',
'shared/express-plugin.md',
'shared/guides/storybook/plugin-overview.md',
'shared/jest-plugin.md',
'shared/js-plugin.md',
'shared/linter-plugin.md',
'shared/nest-plugin.md',
'shared/next-plugin.md',
'shared/node-plugin.md',
'shared/nx-plugin.md',
'shared/react-native-plugin.md',
'shared/react-plugin.md',
'shared/web-plugin.md',
'shared/workspace-plugin.md',
].map((x) => x.replace('.md', ''));
const readmePathList: string[] = glob
.sync(`${basePath}/**/*.md`)
.map((path: string) => path.split(basePath)[1])
.map((path: string) => path.slice(1, -3)) // Removing first `/` and `.md`
.filter((path: string) => !path.startsWith(sharedFilesPattern))
.filter((i) => !allowedOrphanFiles.includes(i)); // Removing the paths allowed to be orphans
function pathExtractor(
pathList: string[] = [],
item: any,
currentPath: string = ''
): string[] {
currentPath = currentPath ? [currentPath, item.id].join('/') : item.id;
if (item.itemList) {
return item.itemList
.map((i: any) => pathExtractor(pathList, i, currentPath))
.flat();
}
if (item.path) {
return pathList;
}
if (item.file) {
pathList.push(item.file);
return pathList;
}
pathList.push(currentPath);
return pathList;
}
const mapPathList: string[] = readJsonSync(`${basePath}/map.json`)
.map((file: any) => pathExtractor([], file, ''))
.flat()
.filter(
// Removing duplicates
(item: string, index: number, array: string[]) =>
array.indexOf(item) === index
)
.filter((item: string) => item.split('/').length > 1); // Removing "category" paths (not linked to a file)
const readmeMissList = readmePathList.filter((x) => !mapPathList.includes(x));
const mapMissList = mapPathList.filter((x) => !readmePathList.includes(x));
let scriptError = false;
if (!!readmeMissList.length) {
console.error(
chalk.red(
"\n⚠ Documentation files and 'map.json' file are out of sync!\n"
)
);
console.log(readmeMissList.map((x) => x.concat('.md')).join('\n'));
console.error(
chalk.red(
`\nSome documentation files exist without any reference in \'map.json\', make sure to add an entry.`
)
);
scriptError = true;
} else {
console.log(
`${chalk.green('✓')} Markdown files are in sync with ${chalk.grey(
'docs/maps.json'
)}.`
);
}
if (!!mapMissList.length) {
console.log(
`\n${chalk.red(
'ERROR'
)} The 'map.json' file and the documentation files are out of sync!\n`
);
console.log(mapMissList.map((x) => x.concat('.md')).join('\n'));
console.log(
`\n${chalk.red(
'ERROR'
)} The \'map.json\' file is linking documentation files that do not exist.`
);
scriptError = true;
} else {
console.log(
`${chalk.green(
'✓'
)} The 'map.json' file and the documentation files are in sync.`
);
}
if (scriptError) {
process.exit(1);
}