@eighty4/changelog
Version:
Changelog utilities for CICD
78 lines (77 loc) • 2.74 kB
JavaScript
import { BadChangelogError, CliError } from "./errors.js";
import { inspectChangelog } from "./inspect.js";
import { readChangelogFile } from "./readChangelog.js";
import { isSemverVersion } from "./semver.js";
export function parseArgs(args) {
const version = args.shift();
if (typeof version === 'undefined') {
throw new CliError('missing version');
}
if (version !== 'Unreleased' && !isSemverVersion(version)) {
throw new CliError(version + ' is not a `vX.X.X` format semver');
}
const opts = {
changelogFile: 'CHANGELOG.md',
version,
};
let shifted;
while ((shifted = args.shift())) {
switch (shifted) {
case '--changelog-file':
if (typeof (shifted = args.shift()) === 'undefined') {
throw new CliError('--changelog-file value is missing');
}
opts.changelogFile = shifted;
break;
default:
throw new CliError(`bad arg \`${shifted}\``);
}
}
return opts;
}
export async function getVersionContentFromCliArgs(args) {
return await getVersionContent(parseArgs(args));
}
export async function getVersionContent(opts) {
const changelogContent = await readChangelogFile(opts.changelogFile);
const inspectResult = inspectChangelog(changelogContent);
if (inspectResult.errors.length) {
throw new BadChangelogError(opts.changelogFile, inspectResult.errors);
}
const versionStartStr = `## [${opts.version}]`;
const versionStart = changelogContent.indexOf(versionStartStr);
if (versionStart === -1) {
throw new Error(opts.version + ' not found');
}
const notesStart = changelogContent.indexOf('\n', versionStart);
let notesEnd = changelogContent.indexOf('\n## ', notesStart);
if (notesEnd === -1) {
notesEnd = changelogContent.indexOf('[', notesStart);
}
if (notesEnd === -1) {
notesEnd = changelogContent.length;
}
const notes = changelogContent.substring(notesStart, notesEnd).trim();
if (!notes.length) {
return '';
}
let result = '';
let categoryLines = [];
const mergeCategoryIntoResult = () => {
if (categoryLines.some(l => /^(\*|\-|\+)/.test(l))) {
result += categoryLines.join('\n');
}
};
for (const l of notes.split(/\r?\n/).map(l => l.trim())) {
if (opts.version === 'Unreleased' && /^(\*|\-|\+) \?\?\?$/.test(l)) {
continue;
}
if (l.startsWith('### ')) {
mergeCategoryIntoResult();
categoryLines = [];
}
categoryLines.push(l);
}
mergeCategoryIntoResult();
return result;
}