| | |
| | import fetch from 'node-fetch' |
| |
|
| | export async function main() { |
| | const releasesArray = await fetch( |
| | 'https://api.github.com/repos/vercel/next.js/releases?per_page=100' |
| | ).then((r) => r.json()) |
| |
|
| | const allReleases = releasesArray |
| | .map(({ id, tag_name, created_at, body }) => ({ |
| | id, |
| | tag_name, |
| | created_at, |
| | body: body |
| | .replace(/\r\n/g, '\n') |
| | .split('\n') |
| | .map((e) => e.trim()), |
| | })) |
| | .sort((a, b) => a.created_at.localeCompare(b.created_at)) |
| |
|
| | |
| | const targetVersion = /v(.*?-)/ |
| | .exec(allReleases.filter((e) => /v.*?-/.exec(e.tag_name)).pop().tag_name) |
| | .pop() |
| |
|
| | const releases = allReleases.filter((v) => v.tag_name.includes(targetVersion)) |
| |
|
| | const lineItems = { |
| | '### Core Changes': [], |
| | '### Minor Changes': [], |
| | '### Documentation Changes': [], |
| | '### Example Changes': [], |
| | '### Misc Changes': [], |
| | '### Patches': [], |
| | '### Credits': [], |
| | } |
| |
|
| | Object.keys(lineItems).forEach((header) => { |
| | releases.forEach((release) => { |
| | const headerIndex = release.body.indexOf(header) |
| |
|
| | if (!~headerIndex) return |
| |
|
| | let headerLastIndex = release.body |
| | .slice(headerIndex + 1) |
| | .findIndex((v) => v.startsWith('###')) |
| |
|
| | if (~headerLastIndex) { |
| | headerLastIndex = headerLastIndex + headerIndex |
| | } else { |
| | headerLastIndex = release.body.length - 1 |
| | } |
| |
|
| | if (header === '### Credits') { |
| | release.body.slice(headerIndex, headerLastIndex + 1).forEach((e) => { |
| | const re = /@[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}/gi |
| | let m |
| |
|
| | do { |
| | m = re.exec(e) |
| |
|
| | if (m) { |
| | lineItems[header].push(m.pop()) |
| | } |
| | } while (m) |
| | }) |
| | } else { |
| | release.body.slice(headerIndex, headerLastIndex + 1).forEach((e) => { |
| | if (!e.startsWith('-')) { |
| | return |
| | } |
| | lineItems[header].push(e) |
| | }) |
| | } |
| | }) |
| | }) |
| |
|
| | let finalMessage = [] |
| |
|
| | Object.keys(lineItems).forEach((header) => { |
| | let items = lineItems[header] |
| |
|
| | if (!items.length) { |
| | return |
| | } |
| | finalMessage.push(header) |
| | finalMessage.push('') |
| |
|
| | if (header === '### Credits') { |
| | items = [...new Set(items)] |
| | let creditsMessage = `Huge thanks to ` |
| |
|
| | if (items.length > 1) { |
| | creditsMessage += items.slice(0, items.length - 1).join(`, `) |
| | creditsMessage += `, and ` |
| | } |
| | creditsMessage += items[items.length - 1] |
| | creditsMessage += ` for helping!` |
| |
|
| | finalMessage.push(creditsMessage) |
| | } else { |
| | items.forEach((e) => finalMessage.push(e)) |
| | } |
| |
|
| | finalMessage.push('') |
| | }) |
| |
|
| | return { |
| | version: targetVersion.slice(0, -1), |
| | firstVersion: releases[0].tag_name, |
| | lastVersion: releases[releases.length - 1].tag_name, |
| | content: finalMessage.join('\n'), |
| | } |
| | } |
| |
|
| | main().then((result) => { |
| | console.log(result.content) |
| | }) |
| |
|