diff --git a/projects-dashboard/src/components/ProjectBadge.astro b/projects-dashboard/src/components/ProjectBadge.astro index 1cf35db..30a88fb 100644 --- a/projects-dashboard/src/components/ProjectBadge.astro +++ b/projects-dashboard/src/components/ProjectBadge.astro @@ -7,12 +7,9 @@ type Props = { badge: Badge; }; -const { - repo, - badge: { type, label, value }, -} = Astro.props; +const { repo, badge } = Astro.props; -const [badgeSrc, href] = getBadgeInfo(repo, type, label, value); +const [badgeSrc, href] = getBadgeInfo(repo, badge); ---
diff --git a/projects-dashboard/src/components/ProjectDetails.astro b/projects-dashboard/src/components/ProjectDetails.astro index 7242fb1..9bfdab1 100644 --- a/projects-dashboard/src/components/ProjectDetails.astro +++ b/projects-dashboard/src/components/ProjectDetails.astro @@ -26,7 +26,9 @@ const {
-

{title ?? repo.name}

+

+ {title ?? repo.name} +

@@ -56,14 +58,16 @@ const {

{description} - {website && ( - <> -
- - {website} - - - )} + { + website && ( + <> +
+ + {website} + + + ) + }

{ diff --git a/projects-dashboard/src/content/config.ts b/projects-dashboard/src/content/config.ts index 169ceae..573ab4a 100644 --- a/projects-dashboard/src/content/config.ts +++ b/projects-dashboard/src/content/config.ts @@ -4,6 +4,7 @@ const repoSchema = z.object({ owner: z.string(), name: z.string(), mainBranch: z.string().optional(), + subPath: z.string().optional(), }); export type Repo = z.infer; @@ -68,6 +69,8 @@ const badgeTypeSchema = z.enum([ "discord", "mailing-list", "github-discussions", + "slack", + "link", ]); export type BadgeType = z.infer; @@ -75,6 +78,7 @@ const badgeSchema = z.object({ type: badgeTypeSchema, label: z.string().optional(), value: z.string().optional(), + token: z.string().optional(), }); export type Badge = z.infer; diff --git a/projects-dashboard/src/lib/badge.ts b/projects-dashboard/src/lib/badge.ts index 62f6e2c..d0836e2 100644 --- a/projects-dashboard/src/lib/badge.ts +++ b/projects-dashboard/src/lib/badge.ts @@ -1,17 +1,23 @@ -import type { BadgeType } from "../content/config"; +import type { Badge, Repo } from "../content/config"; -interface Repo { - owner: string; - name: string; - mainBranch?: string; +interface DefaultBadgeOptions { + label: string; + value?: string; + logo?: string; + color?: string; } -function getDefaultBadgeSource( - type: string, - label: string, - value: string -): string { - return `https://img.shields.io/${type}/${label}-${value}-purple?style=flat-square`; +function getDefaultBadgeSource({ + label, + value, + logo, + color = "purple", +}: DefaultBadgeOptions): string { + const cleanLabel = label.replaceAll("-", "--"); + const cleanValue = value?.replaceAll("-", "--"); + const valueParam = cleanValue ? `-${cleanValue}` : ""; + const logoParam = logo ? `&logo=${logo}` : ""; + return `https://img.shields.io/badge/${cleanLabel}${valueParam}-${color}?style=flat-square${logoParam}`; } function getGithubActionsBadge( @@ -53,9 +59,9 @@ function getOssfBadge(repo: Repo): [string, string] { return [badgeSrc, href]; } -function getCodecovBadge(repo: Repo): [string, string] { +function getCodecovBadge(repo: Repo, token?: string): [string, string] { const branch = repo.mainBranch ?? "main"; - const badgeSrc = `https://img.shields.io/codecov/c/gh/${repo.owner}/${repo.name}/${branch}?label=codecov&style=flat-square&token=YI87CKF1LI`; + const badgeSrc = `https://img.shields.io/codecov/c/gh/${repo.owner}/${repo.name}/${branch}?label=codecov&style=flat-square&token=${token}`; const href = `https://codecov.io/github/${repo.owner}/${repo.name}`; return [badgeSrc, href]; } @@ -177,10 +183,16 @@ function getLifeCycleStatusBadge(value?: string): [string, string] { } function getGithubRepoBadge(repo: Repo): [string, string] { - const badgeValue = `${repo.owner}/${repo.name.replaceAll("-", "--")}`; + const cleanName = repo.name.replaceAll("-", "--"); + const cleanSubPath = repo.subPath ? `/${repo.subPath.replaceAll("-", "--")}` : ""; + const badgeValue = `${repo.owner}/${cleanName}${cleanSubPath}`; const badgeColor = "gray"; const badgeSrc = `https://img.shields.io/badge/-${badgeValue}-${badgeColor}?style=flat-square&logo=github`; - const href = `https://github.com/${repo.owner}/${repo.name}`; + + const branch = repo.mainBranch ?? "main"; + const subPathUrlSuffix = repo.subPath ? `/tree/${branch}/${repo.subPath}` : ""; + const href = `https://github.com/${repo.owner}/${repo.name}${subPathUrlSuffix}`; + return [badgeSrc, href]; } @@ -196,12 +208,57 @@ function getIssuesBadge(repo: Repo): [string, string] { return [badgeSrc, href]; } +function getSlackBadge(label?: string, value?: string): [string, string] { + if (!value) { + throw new Error("Slack URL is required for badge"); + } + + if (!label) { + throw new Error("Slack channel is required for badge"); + } + + if (!label.startsWith("#")) { + throw new Error("Slack channel, in the label field, must start with '#' for badge"); + } + + const channel = `%23${label.slice(1)}`; + + const badgeSrc = getDefaultBadgeSource({ + label: "slack", + value: channel, + color: "blue", + logo: "slack", + }); + + const href = value; + return [badgeSrc, href]; +} + +function getLinkBadge(label?: string, value?: string): [string, string] { + if (!value) { + throw new Error("Link URL is required for badge"); + } + + if (!label) { + throw new Error("Link label is required for badge"); + } + + const badgeSrc = getDefaultBadgeSource({ + label, + color: "purple", + }); + const href = value; + return [badgeSrc, href]; +} + export function getBadgeInfo( repo: Repo, - type: BadgeType, - label?: string, - value?: string + badge: Badge, ): [string, string] { + let { type, label, value, token } = badge; + + // cleanup invalid badge characters + switch (type) { case "github-actions": return getGithubActionsBadge(repo, value, label); @@ -216,7 +273,7 @@ export function getBadgeInfo( case "ossf": return getOssfBadge(repo); case "codecov": - return getCodecovBadge(repo); + return getCodecovBadge(repo, token); case "tbd-vectors": return getTbdVectorsBadge(repo); case "npm": @@ -245,10 +302,11 @@ export function getBadgeInfo( return getIssuesBadge(repo); case "github-discussions": return getGithubDiscussionsBadge(repo); + case "slack": + return getSlackBadge(label, value); + case "link": + return getLinkBadge(label, value); default: - return [ - getDefaultBadgeSource(type, label ?? "badge", value ?? "value"), - "", - ]; + throw new Error(`Unknown badge type: ${type}`); } } diff --git a/projects-dashboard/src/pages/index.astro b/projects-dashboard/src/pages/index.astro index 72bb6ec..dfe0152 100644 --- a/projects-dashboard/src/pages/index.astro +++ b/projects-dashboard/src/pages/index.astro @@ -29,7 +29,7 @@ projects.sort((a, b) => {