72 lines
2.0 KiB
JavaScript
72 lines
2.0 KiB
JavaScript
#!/usr/bin/env node
|
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
const SECTION_BY_TYPE = {
|
|
added: "Added",
|
|
changed: "Changed",
|
|
deprecated: "Deprecated",
|
|
removed: "Removed",
|
|
fixed: "Fixed",
|
|
security: "Security",
|
|
};
|
|
|
|
function usage() {
|
|
console.error([
|
|
"Usage:",
|
|
" pnpm changelog:add -- --type fixed --message \"Fix thing\"",
|
|
"",
|
|
`Types: ${Object.keys(SECTION_BY_TYPE).join(", ")}`,
|
|
].join("\n"));
|
|
process.exit(1);
|
|
}
|
|
|
|
function argValue(name) {
|
|
const index = process.argv.indexOf(`--${name}`);
|
|
if (index === -1) return null;
|
|
return process.argv[index + 1] ?? null;
|
|
}
|
|
|
|
const type = argValue("type")?.toLowerCase();
|
|
const message = argValue("message")?.trim();
|
|
|
|
if (!type || !message || !SECTION_BY_TYPE[type]) {
|
|
usage();
|
|
}
|
|
|
|
const section = SECTION_BY_TYPE[type];
|
|
const changelogPath = resolve("CHANGELOG.md");
|
|
let changelog = readFileSync(changelogPath, "utf8");
|
|
|
|
if (!/^## \[Unreleased\]/m.test(changelog)) {
|
|
changelog = changelog.replace(
|
|
/(\r?\n)(## \[[^\r\n]+\])/,
|
|
`$1## [Unreleased]$1$1$2`,
|
|
);
|
|
}
|
|
|
|
const unreleasedMatch = changelog.match(/^## \[Unreleased\][\s\S]*?(?=^## \[|\z)/m);
|
|
if (!unreleasedMatch) {
|
|
throw new Error("Could not find or create an Unreleased section.");
|
|
}
|
|
|
|
const unreleased = unreleasedMatch[0];
|
|
const lineEnding = changelog.includes("\r\n") ? "\r\n" : "\n";
|
|
const bullet = `- ${message}`;
|
|
|
|
let nextUnreleased;
|
|
const sectionRegex = new RegExp(`(^### ${section}\\s*)([\\s\\S]*?)(?=^### |\\z)`, "m");
|
|
const sectionMatch = unreleased.match(sectionRegex);
|
|
|
|
if (sectionMatch) {
|
|
const body = sectionMatch[2].trimEnd();
|
|
const replacement = `${sectionMatch[1]}${body ? `${body}${lineEnding}` : ""}${bullet}${lineEnding}${lineEnding}`;
|
|
nextUnreleased = unreleased.replace(sectionRegex, replacement);
|
|
} else {
|
|
const insert = `${lineEnding}### ${section}${lineEnding}${lineEnding}${bullet}${lineEnding}`;
|
|
nextUnreleased = unreleased.trimEnd() + insert + lineEnding;
|
|
}
|
|
|
|
changelog = changelog.replace(unreleased, nextUnreleased);
|
|
writeFileSync(changelogPath, changelog);
|