Skip to content

Commit 2e64b3d

Browse files
gatesnclaude
andauthored
Parse RFC authors from markdown frontmatter (#52)
## Summary - Parses `- Authors:` or `**Authors:**` from RFC markdown files - Uses file-specified authors instead of git commit author when present - Falls back to git author if no authors field in the file - Fixes attribution after re-opening RFCs as new PRs ## Test plan - [ ] RFCs with `- Authors:` show the file author (e.g., RFC 0015 shows "Adam Gutglick") - [ ] RFCs without authors field still show git commit author 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent cc5c54d commit 2e64b3d

1 file changed

Lines changed: 28 additions & 5 deletions

File tree

index.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ interface RFC {
2929
filename: string;
3030
html: string;
3131
git: RFCGitInfo;
32+
authors: string[] | null; // parsed from markdown frontmatter, overrides git author
3233
}
3334

3435
interface ProposedRFC {
@@ -151,7 +152,9 @@ function indexPage(
151152
const dateStr = rfc.git.accepted ? formatDate(rfc.git.accepted.date) : "";
152153

153154
let authorHTML = "";
154-
if (rfc.git.author && rfc.git.accepted) {
155+
if (rfc.authors) {
156+
authorHTML = `<span class="rfc-author-name">${rfc.authors.map(escapeHTML).join(", ")}</span>`;
157+
} else if (rfc.git.author && rfc.git.accepted) {
155158
const commitUrl = repoUrl
156159
? `${repoUrl}/commit/${rfc.git.accepted.hash}`
157160
: `https://github.com/${rfc.git.author.login}`;
@@ -235,9 +238,14 @@ function rfcPage(
235238
<span class="rfc-status-pill status-accepted">Accepted</span>
236239
</div>`;
237240

238-
if (rfc.git.accepted || rfc.git.author) {
241+
if (rfc.git.accepted || rfc.git.author || rfc.authors) {
239242
// Author section
240-
if (rfc.git.author) {
243+
if (rfc.authors) {
244+
gitHeader += `
245+
<div class="rfc-meta-item rfc-author">
246+
<span class="author-name">${rfc.authors.map(escapeHTML).join(", ")}</span>
247+
</div>`;
248+
} else if (rfc.git.author) {
241249
gitHeader += `
242250
<div class="rfc-meta-item rfc-author">
243251
<a href="${rfc.git.author.profileUrl}" class="author-link">
@@ -414,6 +422,19 @@ async function validateProposals(): Promise<ValidationError[]> {
414422
return errors;
415423
}
416424

425+
function parseAuthors(markdown: string): string[] | null {
426+
// Match "- Authors: Name1, Name2" or "**Authors:** Name1, Name2"
427+
const match = markdown.match(
428+
/^(?:-\s*Authors:\s*|\*\*Authors:\*\*\s*)(.+)$/im,
429+
);
430+
if (!match?.[1]) return null;
431+
const authors = match[1]
432+
.split(",")
433+
.map((a) => a.trim())
434+
.filter(Boolean);
435+
return authors.length > 0 ? authors : null;
436+
}
437+
417438
function parseTitle(markdown: string, filename: string): string {
418439
// Try to extract title from first # heading
419440
const match = markdown.match(/^#\s+(.+)$/m);
@@ -558,9 +579,10 @@ async function build(liveReload: boolean = false): Promise<number> {
558579
const html = await highlightCodeBlocks(rawHtml);
559580
const number = parseRFCNumber(filename);
560581
const title = parseTitle(content, filename);
582+
const authors = parseAuthors(content);
561583
const git = await getGitHistory(path, repoPath);
562584

563-
rfcs.push({ number, title, filename, html, git });
585+
rfcs.push({ number, title, filename, html, git, authors });
564586
}
565587

566588
if (rfcs.length === 0) {
@@ -716,9 +738,10 @@ async function buildPreview(): Promise<void> {
716738
const html = await highlightCodeBlocks(rawHtml);
717739
const number = parseRFCNumber(filename);
718740
const title = parseTitle(content, filename);
741+
const authors = parseAuthors(content);
719742
const git = await getGitHistory(path, repoPath);
720743

721-
rfcs.push({ number, title, filename, html, git });
744+
rfcs.push({ number, title, filename, html, git, authors });
722745
}
723746

724747
// Build a single self-contained index page with all RFCs and inlined CSS

0 commit comments

Comments
 (0)