|
| 1 | +const { remark } = require('remark'); |
| 2 | + |
1 | 3 | function updateChangelog(changelog) { |
| 4 | + const tree = remark.parse(changelog); |
| 5 | + |
| 6 | + bumpHeadingsLevels(tree); |
| 7 | + linkifyUserTags(tree); |
| 8 | + prettifyPRLinks(tree); |
| 9 | + |
| 10 | + changelog = remark.stringify(tree); |
2 | 11 | changelog = addFrontmatter(changelog); |
3 | | - changelog = pushHeadings(changelog); |
4 | | - changelog = fixUserLinks(changelog); |
5 | | - changelog = fixPRLinks(changelog); |
6 | 12 | changelog = escapeMDXCharacters(changelog); |
7 | 13 | return changelog; |
8 | 14 | } |
9 | 15 |
|
10 | | -function addFrontmatter(changelog, header = 'Changelog') { |
11 | | - return `--- |
12 | | -title: ${header} |
13 | | -sidebar_label: ${header} |
14 | | -toc_max_heading_level: 2 |
15 | | ---- |
16 | | -${changelog}`; |
| 16 | +function bumpHeadingsLevels(tree) { |
| 17 | + tree.children?.forEach((child) => { |
| 18 | + if (child.type === 'heading') { |
| 19 | + child.depth += 1; |
| 20 | + } |
| 21 | + |
| 22 | + bumpHeadingsLevels(child); |
| 23 | + }); |
17 | 24 | } |
18 | 25 |
|
19 | | -function pushHeadings(changelog) { |
20 | | - return changelog.replaceAll(/\n#[^#]/g, '\n## '); |
| 26 | +function linkifyUserTags(tree) { |
| 27 | + for (let i = 0; i < tree.children?.length; i++) { |
| 28 | + const child = tree.children[i]; |
| 29 | + if (child.type === 'text') { |
| 30 | + const userTagRegex = /@([a-zA-Z0-9-]+)(\s|$)/g; |
| 31 | + const match = userTagRegex.exec(child.value); |
| 32 | + |
| 33 | + if (match) { |
| 34 | + const [_, username, ending] = match; |
| 35 | + const before = child.value.slice(0, match.index); |
| 36 | + const after = child.value.slice(userTagRegex.lastIndex); |
| 37 | + |
| 38 | + const link = { |
| 39 | + type: 'link', |
| 40 | + url: `https://github.com/${username}`, |
| 41 | + children: [{ type: 'text', value: `@${username}` }], |
| 42 | + }; |
| 43 | + child.value = before; |
| 44 | + |
| 45 | + tree.children.splice(i + 1, 0, link); |
| 46 | + |
| 47 | + if (after) { |
| 48 | + tree.children.splice(i + 2, 0, { type: 'text', value: `${ending}${after}` }); |
| 49 | + } |
| 50 | + |
| 51 | + i += 2; |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + linkifyUserTags(child); |
| 56 | + } |
21 | 57 | } |
22 | 58 |
|
23 | | -function fixUserLinks(changelog) { |
24 | | - return changelog.replaceAll(/by @([a-zA-Z0-9-]+)/g, 'by [@$1](https://github.com/$1)'); |
| 59 | +// If there is a PR URL (https://github.com/**/**/pull/number) in the text body, split the body, and replace the URL with a link to the PR (the text should be the PR number). |
| 60 | +function prettifyPRLinks(tree) { |
| 61 | + for (let i = 0; i < tree.children?.length; i++) { |
| 62 | + const child = tree.children[i]; |
| 63 | + if (child.type === 'text') { |
| 64 | + const prLinkRegex = /https:\/\/github.com\/.*\/pull\/(\d+)/g; |
| 65 | + const match = prLinkRegex.exec(child.value); |
| 66 | + |
| 67 | + if (match) { |
| 68 | + const [_, prNumber] = match; |
| 69 | + const before = child.value.slice(0, match.index); |
| 70 | + const after = child.value.slice(prLinkRegex.lastIndex); |
| 71 | + |
| 72 | + const link = { |
| 73 | + type: 'link', |
| 74 | + url: match[0], |
| 75 | + children: [{ type: 'text', value: `#${prNumber}` }], |
| 76 | + }; |
| 77 | + child.value = before; |
| 78 | + |
| 79 | + tree.children.splice(i + 1, 0, link); |
| 80 | + |
| 81 | + if (after) { |
| 82 | + tree.children.splice(i + 2, 0, { type: 'text', value: after }); |
| 83 | + } |
| 84 | + |
| 85 | + i += 2; |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + prettifyPRLinks(child); |
| 90 | + } |
25 | 91 | } |
26 | 92 |
|
27 | | -function fixPRLinks(changelog) { |
28 | | - return changelog.replaceAll(/(((https?:\/\/)?(www.)?)?github.com\/[^\s]*?\/pull\/([0-9]+))/g, '[#$5]($1)'); |
| 93 | +function addFrontmatter(changelog, header = 'Changelog') { |
| 94 | + return `--- |
| 95 | +title: ${header} |
| 96 | +sidebar_label: ${header} |
| 97 | +toc_max_heading_level: 3 |
| 98 | +--- |
| 99 | +${changelog}`; |
29 | 100 | } |
30 | 101 |
|
31 | 102 | function escapeMDXCharacters(changelog) { |
|
0 commit comments