|
240 | 240 | return result; |
241 | 241 | } |
242 | 242 |
|
| 243 | + /** |
| 244 | + * Linkify the commit message by wrapping all its non-link text inside |
| 245 | + * markdown links if it already contains a link |
| 246 | + * |
| 247 | + * @param message the commit message |
| 248 | + * @param wrapperUrl the wrapper link to wrap the rest of the message with |
| 249 | + * @returns the formatted commit message |
| 250 | + */ |
| 251 | + function formatCommitMessage(message: string | null | undefined, wrapperUrl: string) { |
| 252 | + if (!message) return `[_No message provided_](${wrapperUrl})`; |
| 253 | + message = message |
| 254 | + .replace(/(https?:\/\/[^ ]+)/g, `[$1]($1)`) |
| 255 | + .replace( |
| 256 | + /\(#(\d+)\)/g, |
| 257 | + `([#$1](https://github.com/${metadata.org}/${metadata.repo}/issues/$1))` |
| 258 | + ); |
| 259 | + const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g; |
| 260 | + const links: { index: number; length: number }[] = []; |
| 261 | + let match; |
| 262 | +
|
| 263 | + while ((match = linkRegex.exec(message)) !== null) { |
| 264 | + links.push({ |
| 265 | + index: match.index, |
| 266 | + length: match[0].length |
| 267 | + }); |
| 268 | + } |
| 269 | +
|
| 270 | + if (!links.length) return `[${message}](${wrapperUrl})`; |
| 271 | +
|
| 272 | + let result = ""; |
| 273 | + let lastIndex = 0; |
| 274 | +
|
| 275 | + for (const link of links) { |
| 276 | + const textBefore = message.slice(lastIndex, link.index); |
| 277 | + if (textBefore.trim()) { |
| 278 | + result += `[${textBefore}](${wrapperUrl})`; |
| 279 | + } |
| 280 | + lastIndex = link.index + link.length; |
| 281 | + result += message.slice(link.index, lastIndex); |
| 282 | + } |
| 283 | +
|
| 284 | + const textAfter = message.slice(lastIndex); |
| 285 | + if (textAfter.trim()) { |
| 286 | + result += `[${textAfter}](${wrapperUrl})`; |
| 287 | + } |
| 288 | +
|
| 289 | + return result; |
| 290 | + } |
| 291 | +
|
243 | 292 | /** |
244 | 293 | * Returns the previous page to go back to |
245 | 294 | */ |
|
562 | 611 | {#each commits as commit (commit.sha)} |
563 | 612 | {@const [commitMessage, ...commitDescriptions] = commit.commit.message.split("\n")} |
564 | 613 | {@const commitDescription = commitDescriptions.join("\n").trim()} |
| 614 | + {@const formattedCommitMessage = formatCommitMessage(commitMessage, commit.html_url)} |
565 | 615 | <Step icon={GitCommitVertical}> |
566 | 616 | <div class="flex flex-col-reverse items-start justify-between sm:flex-row sm:gap-16"> |
567 | 617 | <!-- Left part: commit message, description & author --> |
568 | 618 | <div class="flex flex-col gap-1"> |
569 | 619 | <div> |
570 | | - <!-- eslint-disable-next-line svelte/no-navigation-without-resolve --> |
571 | | - <a href={commit.html_url} class="hover:underline"> |
572 | | - <MarkdownRenderer |
573 | | - markdown={commitMessage ?? "_No message provided_"} |
574 | | - inline |
575 | | - class="prose-p:text-foreground" |
576 | | - /> |
577 | | - </a> |
| 620 | + <MarkdownRenderer |
| 621 | + markdown={formattedCommitMessage} |
| 622 | + inline |
| 623 | + class="prose-p:text-foreground prose-a:hover:underline prose-a:[[href*='/commit/']]:text-foreground" |
| 624 | + /> |
578 | 625 | {#if commit.author} |
579 | 626 | <!-- const to be able to disable eslint without getting owned by prettier wrapping stuff --> |
580 | 627 | {@const authorProfile = commit.author.html_url} |
|
0 commit comments