Skip to content

Commit 5cf675e

Browse files
gatesnclaude
andauthored
Author override (#53)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2e64b3d commit 5cf675e

5 files changed

Lines changed: 81 additions & 54 deletions

File tree

index.ts

Lines changed: 77 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ interface RFC {
2929
filename: string;
3030
html: string;
3131
git: RFCGitInfo;
32-
authors: string[] | null; // parsed from markdown frontmatter, overrides git author
32+
authors: GitHubAuthor[]; // parsed from markdown frontmatter @usernames, or git author fallback
3333
}
3434

3535
interface ProposedRFC {
3636
number: string;
3737
title: string;
3838
prNumber: number;
3939
prUrl: string;
40-
author: GitHubAuthor | null;
40+
authors: GitHubAuthor[];
4141
}
4242

4343
const THEME_SCRIPT = `
@@ -151,19 +151,14 @@ function indexPage(
151151
.map((rfc) => {
152152
const dateStr = rfc.git.accepted ? formatDate(rfc.git.accepted.date) : "";
153153

154-
let authorHTML = "";
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) {
158-
const commitUrl = repoUrl
159-
? `${repoUrl}/commit/${rfc.git.accepted.hash}`
160-
: `https://github.com/${rfc.git.author.login}`;
161-
authorHTML = `
162-
<a href="${commitUrl}" class="rfc-author-link" title="${rfc.git.author.login}">
163-
<img src="${rfc.git.author.avatarUrl}" alt="${rfc.git.author.login}" class="rfc-author-avatar">
164-
<span class="rfc-author-name">${rfc.git.author.login}</span>
165-
</a>`;
166-
}
154+
const authorHTML = rfc.authors
155+
.map(
156+
(author) => `
157+
<a href="${author.profileUrl}" class="rfc-author-link" title="${author.login}">
158+
<img src="${author.avatarUrl}" alt="${author.login}" class="rfc-author-avatar">
159+
</a>`,
160+
)
161+
.join("");
167162

168163
return `
169164
<li>
@@ -180,14 +175,14 @@ function indexPage(
180175
if (proposed.length > 0) {
181176
const proposedList = proposed
182177
.map((rfc) => {
183-
let authorHTML = "";
184-
if (rfc.author) {
185-
authorHTML = `
186-
<a href="${rfc.author.profileUrl}" class="rfc-author-link" title="${rfc.author.login}">
187-
<img src="${rfc.author.avatarUrl}" alt="${rfc.author.login}" class="rfc-author-avatar">
188-
<span class="rfc-author-name">${rfc.author.login}</span>
189-
</a>`;
190-
}
178+
const authorHTML = rfc.authors
179+
.map(
180+
(author) => `
181+
<a href="${author.profileUrl}" class="rfc-author-link" title="${author.login}">
182+
<img src="${author.avatarUrl}" alt="${author.login}" class="rfc-author-avatar">
183+
</a>`,
184+
)
185+
.join("");
191186

192187
return `
193188
<li>
@@ -238,20 +233,20 @@ function rfcPage(
238233
<span class="rfc-status-pill status-accepted">Accepted</span>
239234
</div>`;
240235

241-
if (rfc.git.accepted || rfc.git.author || rfc.authors) {
242-
// Author section
243-
if (rfc.authors) {
236+
if (rfc.git.accepted || rfc.authors.length > 0) {
237+
if (rfc.authors.length > 0) {
238+
const authorsHTML = rfc.authors
239+
.map(
240+
(author) => `
241+
<a href="${author.profileUrl}" class="author-link">
242+
<img src="${author.avatarUrl}" alt="${author.login}" class="author-avatar">
243+
<span class="author-name">${author.login}</span>
244+
</a>`,
245+
)
246+
.join(", ");
244247
gitHeader += `
245248
<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) {
249-
gitHeader += `
250-
<div class="rfc-meta-item rfc-author">
251-
<a href="${rfc.git.author.profileUrl}" class="author-link">
252-
<img src="${rfc.git.author.avatarUrl}" alt="${rfc.git.author.login}" class="author-avatar">
253-
<span class="author-name">${rfc.git.author.login}</span>
254-
</a>
249+
${authorsHTML}
255250
</div>`;
256251
}
257252

@@ -422,17 +417,24 @@ async function validateProposals(): Promise<ValidationError[]> {
422417
return errors;
423418
}
424419

425-
function parseAuthors(markdown: string): string[] | null {
426-
// Match "- Authors: Name1, Name2" or "**Authors:** Name1, Name2"
420+
function parseAuthorLogins(markdown: string): string[] {
421+
// Match "- Authors: @user1, @user2" or "**Authors:** @user1, @user2"
427422
const match = markdown.match(
428423
/^(?:-\s*Authors:\s*|\*\*Authors:\*\*\s*)(.+)$/im,
429424
);
430-
if (!match?.[1]) return null;
431-
const authors = match[1]
425+
if (!match?.[1]) return [];
426+
return match[1]
432427
.split(",")
433-
.map((a) => a.trim())
428+
.map((a) => a.trim().replace(/^@/, ""))
434429
.filter(Boolean);
435-
return authors.length > 0 ? authors : null;
430+
}
431+
432+
function loginsToAuthors(logins: string[]): GitHubAuthor[] {
433+
return logins.map((login) => ({
434+
login,
435+
avatarUrl: `https://github.com/${login}.png?size=48`,
436+
profileUrl: `https://github.com/${login}`,
437+
}));
436438
}
437439

438440
function parseTitle(markdown: string, filename: string): string {
@@ -510,7 +512,7 @@ async function getProposedRFCs(
510512
if (!repoPath) return [];
511513
try {
512514
const result =
513-
await $`gh pr list --repo ${repoPath} --state open --json number,title,url,files,author`.quiet();
515+
await $`gh pr list --repo ${repoPath} --state open --json number,title,url,files,author,headRefName`.quiet();
514516
const prs = JSON.parse(result.stdout.toString());
515517
const proposed: ProposedRFC[] = [];
516518

@@ -527,18 +529,30 @@ async function getProposedRFCs(
527529
const rfcNumber = rfcFile.path.match(/(\d{4})-/)?.[1];
528530
if (!rfcNumber) continue;
529531

532+
// Fetch file content from PR branch to parse authors
533+
let authors: GitHubAuthor[] = [];
534+
try {
535+
const fileResult =
536+
await $`gh api repos/${repoPath}/contents/${rfcFile.path}?ref=${pr.headRefName} --jq '.content'`.quiet();
537+
const content = atob(fileResult.stdout.toString().trim());
538+
const logins = parseAuthorLogins(content);
539+
if (logins.length > 0) {
540+
authors = loginsToAuthors(logins);
541+
}
542+
} catch {
543+
// Fall back to PR author
544+
}
545+
546+
if (authors.length === 0 && pr.author) {
547+
authors = loginsToAuthors([pr.author.login]);
548+
}
549+
530550
proposed.push({
531551
number: rfcNumber,
532552
title: pr.title,
533553
prNumber: pr.number,
534554
prUrl: pr.url,
535-
author: pr.author
536-
? {
537-
login: pr.author.login,
538-
avatarUrl: `https://github.com/${pr.author.login}.png?size=48`,
539-
profileUrl: `https://github.com/${pr.author.login}`,
540-
}
541-
: null,
555+
authors,
542556
});
543557
}
544558

@@ -579,8 +593,14 @@ async function build(liveReload: boolean = false): Promise<number> {
579593
const html = await highlightCodeBlocks(rawHtml);
580594
const number = parseRFCNumber(filename);
581595
const title = parseTitle(content, filename);
582-
const authors = parseAuthors(content);
596+
const authorLogins = parseAuthorLogins(content);
583597
const git = await getGitHistory(path, repoPath);
598+
const authors =
599+
authorLogins.length > 0
600+
? loginsToAuthors(authorLogins)
601+
: git.author
602+
? [git.author]
603+
: [];
584604

585605
rfcs.push({ number, title, filename, html, git, authors });
586606
}
@@ -738,8 +758,14 @@ async function buildPreview(): Promise<void> {
738758
const html = await highlightCodeBlocks(rawHtml);
739759
const number = parseRFCNumber(filename);
740760
const title = parseTitle(content, filename);
741-
const authors = parseAuthors(content);
761+
const authorLogins = parseAuthorLogins(content);
742762
const git = await getGitHistory(path, repoPath);
763+
const authors =
764+
authorLogins.length > 0
765+
? loginsToAuthors(authorLogins)
766+
: git.author
767+
? [git.author]
768+
: [];
743769

744770
rfcs.push({ number, title, filename, html, git, authors });
745771
}

rfcs/0000-template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
- Start Date: YYYY-MM-DD (today's date)
2-
- Authors: John Smith, Foo Bar
2+
- Authors: @username1, @username2
33
- RFC PR: [vortex-data/rfcs#0000](https://github.com/vortex-data/rfcs/pull/0000)
44

55
# RFC Template

rfcs/0015-variant-type.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
- Start Date: 2025-02-25
2-
- Authors: Adam Gutglick
2+
- Authors: @AdamGS
33
- RFC PR: [vortex-data/rfcs#15](https://github.com/vortex-data/rfcs/pull/15)
44

55
# Variant Type

rfcs/0024-tensor.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
- Start Date: 2026-03-04
2-
- Authors: Connor Tsui
2+
- Authors: @connortsui20
33
- RFC PR: [vortex-data/rfcs#24](https://github.com/vortex-data/rfcs/pull/24)
44

55
# Fixed-shape Tensor Extension

rfcs/0027-patches-format.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
- Start Date: 2026-03-02
2+
- Authors: @a10y
23
- Tracking Issue: TBD
34
- Draft PR: https://github.com/vortex-data/vortex/pull/6815
45

0 commit comments

Comments
 (0)