Skip to content

Commit 47d616b

Browse files
committed
fix: normalizeTitlePrefixes
1 parent 883d559 commit 47d616b

File tree

1 file changed

+46
-29
lines changed

1 file changed

+46
-29
lines changed

.github/scripts/release-notes.js

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,39 +77,59 @@ async function getLinkedIssues(prNumber) {
7777

7878
// --- Classify title by flexible prefix ---
7979
function classifyTitle(title) {
80-
// remove leading emoji and spaces
81-
const cleaned = title.replace(/^[\s\p{Emoji_Presentation}\p{Extended_Pictographic}]+/u, '');
80+
// Remove emojis and spaces at start
81+
const cleaned = title.replace(/^[\s\p{Emoji_Presentation}\p{Extended_Pictographic}]+/u, "");
82+
83+
// Match [Feat], Feat:, Feat - etc.
8284
const match = cleaned.match(/^\s*(?:\[([^\]]+)\]|([^\s:]+))\s*:?\s*/i);
83-
const rawPrefix = match ? (match[1] || match[2]) : null;
85+
if (!match) return "Other";
86+
87+
// If multiple prefixes inside [Feat, Enhancement] — split and take first
88+
let rawPrefix = (match[1] || match[2])?.split(",")[0].trim() || null;
8489
if (!rawPrefix) return "Other";
8590

8691
const prefix = rawPrefix.toLowerCase();
8792
const map = {
88-
"task": "🚀 Tasks",
89-
"composite": "🚀 Tasks",
93+
task: "🚀 Tasks",
94+
composite: "🚀 Tasks",
9095
"ux/ui": "🔧 Enhancements",
91-
"enhancement": "🔧 Enhancements",
92-
"bug": "🐞 Bug Fixes",
93-
"feat": "✨ New Features",
94-
"refactor": "🛠 Refactoring",
95-
"docs": "📚 Documentation",
96-
"test": "✅ Tests",
97-
"chore": "⚙️ Chores",
98-
"proposal": "💡 Ideas & Proposals",
99-
"idea": "💡 Ideas & Proposals",
100-
"discussion": "💡 Ideas & Proposals",
96+
enhancement: "🔧 Enhancements",
97+
bug: "🐞 Bug Fixes",
98+
feat: "✨ New Features",
99+
feature: "✨ New Features",
100+
refactor: "🛠 Refactoring",
101+
docs: "📚 Documentation",
102+
doc: "📚 Documentation",
103+
test: "✅ Tests",
104+
chore: "⚙️ Chores",
105+
proposal: "💡 Ideas & Proposals",
106+
idea: "💡 Ideas & Proposals",
107+
discussion: "💡 Ideas & Proposals",
101108
};
102109

103110
return map[prefix] || "Other";
104111
}
105112

113+
// --- Normalize prefix style in titles ---
114+
function normalizeTitlePrefixes(title) {
115+
return title.replace(/^\s*(?:\[([^\]]+)\]|([^\s:]+))\s*:?\s*/i, (match, p1, p2) => {
116+
const prefixText = p1 || p2;
117+
if (!prefixText) return match;
118+
// Preserve multiple prefixes, capitalize each, wrap in [ ]
119+
const formatted = prefixText
120+
.split(",")
121+
.map(p => `[${p.trim().charAt(0).toUpperCase() + p.trim().slice(1).toLowerCase()}]`)
122+
.join(" ");
123+
return `${formatted} `;
124+
});
125+
}
126+
106127
// --- Semantic versioning ---
107128
function nextVersion(lastTag) {
108129
if (!lastTag) return "v0.1.0";
109130
const match = lastTag.match(/^v(\d+)\.(\d+)\.(\d+)/);
110131
if (!match) return "v0.1.0";
111-
112-
let [_, major, minor, patch] = match.map(Number);
132+
let [, major, minor, patch] = match.map(Number);
113133
patch += 1;
114134
return `v${major}.${minor}.${patch}`;
115135
}
@@ -163,7 +183,7 @@ async function main() {
163183
}
164184
}
165185

166-
// 5️⃣ Classify
186+
// 5️⃣ Classify and build sections
167187
const sections = {
168188
"🚀 Tasks": [],
169189
"🔧 Enhancements": [],
@@ -179,17 +199,15 @@ async function main() {
179199

180200
for (const [num, info] of Object.entries(issueMap)) {
181201
const section = classifyTitle(info.title);
182-
sections[section].push(
183-
`#${num} ${info.title} ↳ PRs: ${info.prs
184-
.sort((a, b) => a - b) // сортировка по возрастанию
185-
.map(n => `#${n}`)
186-
.join(", ")}`
187-
);
202+
const title = normalizeTitlePrefixes(info.title);
203+
const prsText = info.prs.sort((a, b) => a - b).map(n => `#${n}`).join(", ");
204+
sections[section].push(`#${num} ${title}\n↳ PRs: ${prsText}`);
188205
}
189206

190207
for (const pr of prsWithoutIssue) {
191208
const section = classifyTitle(pr.title);
192-
sections[section].push(`#${pr.number} ${pr.title}`);
209+
const title = normalizeTitlePrefixes(pr.title);
210+
sections[section].push(`#${pr.number} ${title}`);
193211
}
194212

195213
// 6️⃣ Build release notes text
@@ -203,15 +221,15 @@ async function main() {
203221
}
204222

205223
console.log(releaseNotesText);
206-
// --- Find or create draft release ---
224+
225+
// 7️⃣ Find or create draft release
207226
let draftRelease = null;
208227
try {
209228
const { data: releases } = await octokit.repos.listReleases({ owner: OWNER, repo: REPO, per_page: 10 });
210229
draftRelease = releases.find(r => r.draft);
211230
} catch {}
212231

213232
if (draftRelease) {
214-
// Update existing draft
215233
await octokit.repos.updateRelease({
216234
owner: OWNER,
217235
repo: REPO,
@@ -221,7 +239,6 @@ async function main() {
221239
});
222240
console.log(`✅ Draft release updated: ${draftRelease.tag_name}`);
223241
} else {
224-
// Create new draft
225242
await octokit.repos.createRelease({
226243
owner: OWNER,
227244
repo: REPO,
@@ -234,7 +251,7 @@ async function main() {
234251
console.log(`✅ Draft release created: ${newTag}`);
235252
}
236253

237-
console.log(`✅ Release created: ${newTag}`);
254+
console.log(`✅ Release processing completed`);
238255
}
239256

240257
// --- Run ---

0 commit comments

Comments
 (0)