UNPKG

@taiga-ui/auto-changelog-config

Version:
185 lines (143 loc) 5.68 kB
/* eslint-disable @typescript-eslint/no-invalid-this */ module.exports = function (Handlebars) { const firstNonEmptyString = (...values) => values.map((value) => String(value ?? '').trim()).find(Boolean) ?? ''; const toArray = (value) => (Array.isArray(value) ? value : []); const escape = (value) => String(value ?? '').trim(); const commitPattern = /^(?:build|chore|ci|docs|feat|fix|refactor|revert|style|test)\s?(?:\((?<scope>[^)]*)\))?!?: (?<title>.*)$/; const publicChangePattern = /^(?:feat|fix)(?:\([^)]*\))?!?:/; const getPullRequestId = (href) => { const [, id = ''] = String(href ?? '').match( /\/(?:pull|merge_requests|pull-requests)\/(\d+)(?:$|[/?#])/, ) ?? []; return id; }; const getPullRequestIdFromText = (text) => { const [, id = ''] = String(text ?? '').match(/\s\(#(\d+)\)\s*$/) ?? []; return id; }; const getPullRequest = (merge, subject) => { const href = firstNonEmptyString(merge.href, merge.pullRequest?.href); const id = firstNonEmptyString( merge.id, merge.number, merge.pullRequest?.id, merge.pullRequest?.number, getPullRequestId(href), getPullRequestIdFromText(merge.message), getPullRequestIdFromText(subject), ); if (!id) { return; } return { id, href, }; }; const getPullRequestFromCommit = (commit) => { const subject = firstNonEmptyString(commit.subject, commit.message); const id = getPullRequestIdFromText(subject); if (!id) { return; } return {id}; }; const normalizeMerge = (merge) => { const commit = merge.commit ?? {}; const subject = firstNonEmptyString(commit.subject, merge.message); return { ...commit, href: firstNonEmptyString(commit.href), pullRequest: getPullRequest(merge, subject), shorthash: firstNonEmptyString(commit.shorthash, merge.shorthash), subject, }; }; const normalizeCommit = (commit) => ({ ...commit, href: firstNonEmptyString(commit.href), pullRequest: commit.pullRequest ?? getPullRequestFromCommit(commit), shorthash: firstNonEmptyString(commit.shorthash), subject: firstNonEmptyString(commit.subject, commit.message), }); const getCommitKey = (commit) => firstNonEmptyString( commit.pullRequest?.id ? `pr:${commit.pullRequest.id}` : '', commit.hash ? `hash:${commit.hash}` : '', commit.shorthash ? `hash:${commit.shorthash}` : '', commit.href, commit.subject, ); const uniqueCommits = (commits) => [ ...commits .reduce((map, commit) => { const key = getCommitKey(commit); if (key && !map.has(key)) { map.set(key, commit); } return map; }, new Map()) .values(), ]; const formatCommitTitle = (subject) => { const string = String(subject ?? '').trim(); const {scope = '', title = ''} = commitPattern.exec(string)?.groups ?? {}; const cleanTitle = title.replace(/\s\(#\d+\)\s*$/, ''); if (!cleanTitle) { return escape(string || 'empty commit name'); } return scope ? `**${escape(scope.toLowerCase())}**: ${escape(cleanTitle)}` : escape(cleanTitle); }; const formatPullRequestReference = (commit) => { const pullRequest = commit.pullRequest; if (!pullRequest?.id) { return ''; } const text = `#${escape(pullRequest.id)}`; return pullRequest.href ? `([${text}](${escape(pullRequest.href)}))` : `(${text})`; }; const formatCommitReference = (commit) => { if (!commit.shorthash) { return ''; } const text = `(${escape(commit.shorthash)})`; return commit.href ? `[${text}](${escape(commit.href)})` : text; }; const formatChangelogEntry = (commit) => [ formatCommitTitle(commit.subject), formatPullRequestReference(commit), formatCommitReference(commit), ] .filter(Boolean) .join(' '); Handlebars.registerHelper('commit-parser', function (merges, commits, options) { const commitsFromMerges = toArray(merges).map(normalizeMerge); const directCommits = toArray(commits).map(normalizeCommit); const result = uniqueCommits(commitsFromMerges.concat(directCommits)); return options.fn(result); }); Handlebars.registerHelper('replaceCommit', function (context) { return new Handlebars.SafeString(formatCommitTitle(context.fn(this))); }); Handlebars.registerHelper('changelogEntry', function () { return new Handlebars.SafeString(formatChangelogEntry(this)); }); Handlebars.registerHelper('replaceTitle', function (context) { const string = String(context.fn(this)).trim(); return string.replace(/^v/, ''); }); Handlebars.registerHelper('if-public-changes', function (commits, options) { const hasPublicChanges = toArray(commits).some((commit) => publicChangePattern.test(firstNonEmptyString(commit.subject, commit.message)), ); return hasPublicChanges ? options.fn(this) : options.inverse(this); }); };