From 3e40878a88eeb609da3faa5953dd8415b91e1ec8 Mon Sep 17 00:00:00 2001 From: suyua9 <1521777066@qq.com> Date: Mon, 27 Apr 2026 06:16:34 +0800 Subject: [PATCH] fix: avoid GitHub links for email contributors (#1167) * fix: avoid GitHub links for email contributors * test: address contributor formatter review * test: leave generated prompts untouched --- scripts/generate-contributors.sh | 15 ++++++++++++- tests/generate-contributors-format.test.js | 26 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/generate-contributors-format.test.js diff --git a/scripts/generate-contributors.sh b/scripts/generate-contributors.sh index b79989a4..f14f41e3 100755 --- a/scripts/generate-contributors.sh +++ b/scripts/generate-contributors.sh @@ -131,13 +131,26 @@ def git_commit(author_name, author_email, message): # --- PROMPTS.md helpers --- +EMAIL_RE = re.compile(r'^[^@\s]+@[^@\s]+\.[^@\s]+$') +GITHUB_USERNAME_RE = re.compile(r'^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$') + def format_contributor_links(contributor_field): if not contributor_field: return '@anonymous' contributors = [c.strip() for c in contributor_field.split(',') if c.strip()] if not contributors: return '@anonymous' - return ', '.join([f'[@{c}](https://github.com/{c})' for c in contributors]) + + links = [] + for contributor in contributors: + normalized = contributor.lstrip('@') + if EMAIL_RE.match(normalized): + links.append('@anonymous') + elif GITHUB_USERNAME_RE.match(normalized): + links.append(f'[@{normalized}](https://github.com/{normalized})') + elif normalized: + links.append(f'@{normalized}') + return ', '.join(links) if links else '@anonymous' def generate_prompt_block(row): act = row.get('act', 'Untitled') diff --git a/tests/generate-contributors-format.test.js b/tests/generate-contributors-format.test.js new file mode 100644 index 00000000..e89fdba2 --- /dev/null +++ b/tests/generate-contributors-format.test.js @@ -0,0 +1,26 @@ +import assert from "node:assert"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const repoRoot = path.resolve(__dirname, ".."); +const generator = fs.readFileSync(path.join(repoRoot, "scripts/generate-contributors.sh"), "utf8"); + +assert.ok(generator.includes("EMAIL_RE"), "generator should detect email contributors"); +assert.ok(generator.includes("GITHUB_USERNAME_RE"), "generator should validate GitHub usernames"); +assert.ok(generator.includes("{0,38}"), "GitHub usernames up to 39 characters should be accepted"); +assert.ok( + generator.includes("links.append('@anonymous')"), + "email contributors should render as anonymous instead of GitHub profile links", +); +assert.ok( + generator.includes("normalized = contributor.lstrip('@')"), + "contributors with a leading @ should be normalized before rendering", +); +assert.ok( + generator.includes("elif normalized:"), + "non-email non-GitHub contributor names should still render as plain text", +); + +console.log("Passed: 5");