scripts/maintain-readme/index.mjs (85 lines of code) (raw):
import { readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { pathFromRoot, projectRoot } from '../project-paths.mjs';
import { getPackageList } from './get-package-list.mjs';
import { getMakeTargets } from '../lib/get-make-targets.mjs';
import { format } from 'prettier';
import prettierConfig from '@guardian/prettier';
import { getTasksByPackage } from '../lib/get-tasks-by-package.mjs';
import _updateSection from 'update-section';
/**
*
* @param {object} options
* @param {string} options.contents
* @param {string} options.tag
* @param {string} options.updates
* @param {string} options.updater
* @returns string
*/
const updateSection = ({ contents, tag, updates, updater }) => {
const START = `<!-- START ${tag} -->`;
const END = `<!-- END ${tag} -->`;
/** @param {string} line */
function matchesStart(line) {
return line.includes(START);
}
/** @param {string} line */
function matchesEnd(line) {
return line.includes(END);
}
return _updateSection(
contents,
[
START,
`<!-- THIS CONTENT IS AUTOGENERATED BY ${updater} -->`,
'',
updates,
'',
END,
].join('\n'),
matchesStart,
matchesEnd,
);
};
const thisFilePath = fileURLToPath(import.meta.url);
const thisFilePathFromRoot = pathFromRoot(thisFilePath);
const readMePath = path.resolve(projectRoot, 'README.md');
let contents = await readFile(readMePath, 'utf8');
contents = updateSection({
contents,
tag: 'PUBLISHED_PACKAGES',
updates: await getPackageList(),
updater: thisFilePathFromRoot,
});
const makeTargets = await getMakeTargets();
const makeTargetsList = makeTargets
.map(({ target, description }) => `- \`make ${target}\` _${description}_`)
.join('\n');
const tasks = await getTasksByPackage();
const tasksList = [
'### Project-specific tasks',
'Project-specific tasks are defined as `scripts` in their `package.json`, and can be run with `make <project>:<script>`:',
'',
];
let currentPkg = '';
for (const tasksByPkg of tasks) {
const [thisPkg, scripts] = tasksByPkg;
if (thisPkg !== currentPkg) {
currentPkg = thisPkg;
tasksList.push(`#### ${currentPkg}`);
}
for (const script of scripts) {
tasksList.push(`- \`make ${thisPkg}:${script}\``);
}
}
contents = updateSection({
contents,
tag: 'TASKS',
updates: makeTargetsList + '\n\n' + tasksList.join('\n'),
updater: thisFilePathFromRoot,
});
await writeFile(
readMePath,
await format(contents, { filepath: readMePath, ...prettierConfig }),
);