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 {
{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) => {