Files
test-repo/scripts/draft-blog-post.mjs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

170 lines
4.8 KiB
JavaScript
Raw Normal View History

2020-03-21 22:24:23 +02:00
#!/usr/bin/env node
2021-05-15 20:09:52 +08:00
import fs from "node:fs";
import path from "node:path";
import rimraf from "rimraf";
import semver from "semver";
import createEsmUtils from "esm-utils";
2020-03-21 22:24:23 +02:00
2021-05-15 20:09:52 +08:00
const { __dirname, require } = createEsmUtils(import.meta);
2020-03-21 22:24:23 +02:00
const changelogUnreleasedDir = path.join(__dirname, "../changelog_unreleased");
const blogDir = path.join(__dirname, "../website/blog");
const introTemplateFile = path.join(
changelogUnreleasedDir,
"BLOG_POST_INTRO_TEMPLATE.md"
);
2020-03-21 22:24:23 +02:00
const introFile = path.join(changelogUnreleasedDir, "blog-post-intro.md");
if (!fs.existsSync(introFile)) {
fs.copyFileSync(introTemplateFile, introFile);
}
const previousVersion = require("prettier/package.json").version;
2020-03-21 22:24:23 +02:00
const version = require("../package.json").version.replace(/-.+/, "");
const postGlob = path.join(blogDir, `????-??-??-${version}.md`);
const postFile = path.join(
blogDir,
`${new Date().toISOString().replace(/T.+/, "")}-${version}.md`
);
const categories = [
{ dir: "javascript", title: "JavaScript" },
{ dir: "typescript", title: "TypeScript" },
{ dir: "flow", title: "Flow" },
{ dir: "json", title: "JSON" },
{ dir: "css", title: "CSS" },
{ dir: "scss", title: "SCSS" },
{ dir: "less", title: "Less" },
{ dir: "html", title: "HTML" },
{ dir: "vue", title: "Vue" },
{ dir: "angular", title: "Angular" },
{ dir: "lwc", title: "LWC" },
{ dir: "handlebars", title: "Ember / Handlebars" },
2020-03-21 22:24:23 +02:00
{ dir: "graphql", title: "GraphQL" },
{ dir: "markdown", title: "Markdown" },
{ dir: "mdx", title: "MDX" },
{ dir: "yaml", title: "YAML" },
{ dir: "api", title: "API" },
{ dir: "cli", title: "CLI" },
];
const categoriesByDir = categories.reduce((result, category) => {
result[category.dir] = category;
return result;
}, {});
const dirs = fs
.readdirSync(changelogUnreleasedDir, { withFileTypes: true })
.filter((entry) => entry.isDirectory());
for (const dir of dirs) {
const dirPath = path.join(changelogUnreleasedDir, dir.name);
const category = categoriesByDir[dir.name];
if (!category) {
throw new Error("Unknown category: " + dir.name);
}
category.entries = fs
2020-11-16 14:17:36 +09:00
.readdirSync(dirPath)
.filter((fileName) => /^\d+\.md$/.test(fileName))
2020-03-21 22:24:23 +02:00
.map((fileName) => {
const [title, ...rest] = fs
.readFileSync(path.join(dirPath, fileName), "utf8")
.trim()
.split("\n");
2021-05-10 00:15:27 +03:00
const improvement = title.match(/\[IMPROVEMENT(:(\d+))?]/);
const section = title.includes("[HIGHLIGHT]")
? "highlight"
: title.includes("[BREAKING]")
? "breaking"
: improvement
? "improvement"
: undefined;
const order =
section === "improvement" && improvement[2] !== undefined
? Number(improvement[2])
: undefined;
const content = [processTitle(title), ...rest].join("\n");
return { fileName, section, order, content };
2020-03-21 22:24:23 +02:00
});
}
rimraf.sync(postGlob);
fs.writeFileSync(
postFile,
replaceVersions(
[
fs.readFileSync(introFile, "utf8").trim(),
"<!--truncate-->",
...printEntries({
title: "Highlights",
2021-05-10 00:15:27 +03:00
filter: (entry) => entry.section === "highlight",
}),
...printEntries({
2021-05-10 00:15:27 +03:00
title: "Breaking Changes",
filter: (entry) => entry.section === "breaking",
}),
...printEntries({
2021-05-10 00:15:27 +03:00
title: "Formatting Improvements",
filter: (entry) => entry.section === "improvement",
}),
...printEntries({
title: "Other Changes",
filter: (entry) => !entry.section,
}),
].join("\n\n") + "\n"
)
2020-03-21 22:24:23 +02:00
);
function processTitle(title) {
return title
2021-05-10 00:15:27 +03:00
.replace(/\[(BREAKING|HIGHLIGHT|IMPROVEMENT(:\d+)?)]/g, "")
.replace(/\s+/g, " ")
.replace(/^#{4} [a-z]/, (s) => s.toUpperCase())
.replace(/(?<![[`])@([\w-]+)/g, "[@$1](https://github.com/$1)")
.replace(
/(?<![[`])#(\d{4,})/g,
"[#$1](https://github.com/prettier/prettier/pull/$1)"
);
}
2020-03-21 22:24:23 +02:00
function printEntries({ title, filter }) {
const result = [];
for (const { entries = [], title } of categories) {
const filteredEntries = entries.filter(filter);
if (filteredEntries.length > 0) {
2021-05-10 00:15:27 +03:00
filteredEntries.sort((a, b) => {
if (a.order !== undefined) {
return b.order === undefined ? 1 : a.order - b.order;
}
return a.fileName.localeCompare(b.fileName, "en", { numeric: true });
});
2021-01-24 04:37:01 +08:00
result.push(
"### " + title,
...filteredEntries.map((entry) => entry.content)
);
2020-03-21 22:24:23 +02:00
}
}
if (result.length > 0) {
2020-03-21 22:24:23 +02:00
result.unshift("## " + title);
}
return result;
}
function formatVersion(version) {
return `${semver.major(version)}.${semver.minor(version)}`;
}
function replaceVersions(data) {
return data
.replace(/prettier stable/gi, `Prettier ${formatVersion(previousVersion)}`)
2021-01-24 01:14:13 +08:00
.replace(/prettier main/gi, `Prettier ${formatVersion(version)}`);
}