aboutsummaryrefslogtreecommitdiff
path: root/scripts/shared/commits.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/shared/commits.mjs')
-rw-r--r--scripts/shared/commits.mjs54
1 files changed, 54 insertions, 0 deletions
diff --git a/scripts/shared/commits.mjs b/scripts/shared/commits.mjs
new file mode 100644
index 0000000..aaccb4d
--- /dev/null
+++ b/scripts/shared/commits.mjs
@@ -0,0 +1,54 @@
+import _ from 'lodash';
+
+export { rawCommitsToMarkdown };
+
+const commitScopesToHumanReadable = {
+ build: 'Build system',
+ chore: 'Chores',
+ ci: 'Continuous integration',
+ docs: 'Documentation',
+ feat: 'Features',
+ fix: 'Bug fixes',
+ infra: 'Infrastucture',
+ perf: 'Performance',
+ refactor: 'Refactoring',
+ test: 'Tests',
+};
+
+const commitTypesOrder = ['feat', 'fix', 'perf', 'refactor', 'test', 'build', 'ci', 'chore', 'other'];
+
+const getCommitTypeSortIndex = (type) =>
+ commitTypesOrder.includes(type) ? commitTypesOrder.indexOf(type) : commitTypesOrder.length;
+
+function parseCommitLine(commit) {
+ const [sha, ...splittedRawMessage] = commit.trim().split(' ');
+ const rawMessage = splittedRawMessage.join(' ');
+ const { type, scope, subject } = /^(?<type>.*?)(\((?<scope>.*)\))?: ?(?<subject>.+)$/.exec(rawMessage)?.groups ?? {};
+
+ return {
+ sha: sha.slice(0, 7),
+ type: type ?? 'other',
+ scope,
+ subject: subject ?? rawMessage,
+ };
+}
+
+function commitSectionsToMarkdown({ type, commits }) {
+ return [
+ `### ${commitScopesToHumanReadable[type] ?? _.capitalize(type)}`,
+ ...commits.map(({ sha, scope, subject }) => ['-', scope ? `**${scope}**:` : '', subject, `(${sha})`].join(' ')),
+ ].join('\n');
+}
+
+function rawCommitsToMarkdown({ rawCommits }) {
+ return _.chain(rawCommits)
+ .trim()
+ .split('\n')
+ .map(parseCommitLine)
+ .groupBy('type')
+ .map((commits, type) => ({ type, commits }))
+ .sortBy(({ type }) => getCommitTypeSortIndex(type))
+ .map(commitSectionsToMarkdown)
+ .join('\n\n')
+ .value();
+}