98 lines · 2.9 KB
/** Social card URLs and their version hashes; shared by page heads (client and server) and the /og handler. */

/** Bump when a card layout changes so every cached card URL changes with it. */
export const OG_RENDERER_VERSION = "1";
export const OG_WIDTH = 1200;
export const OG_HEIGHT = 630;
export const OG_PREFIX = "/og/";
export const SITE_OG_PATH = "/og/site.png";
export const SITE_DESCRIPTION =
  "gitfor hosts Git repositories with pull requests, Actions-style CI, issues, security scanning and sites. Open source under 0BSD, and you can run your own instance.";
export const SITE_OG_ALT = "gitfor: open-source Git hosting, code review and CI";

/** FNV-1a 32-bit over the joined fields: cheap, sync and stable on both sides; it only needs to change, not resist collisions. */
export function ogVersion(fields: ReadonlyArray<string | number | null | undefined>): string {
  const input = [
    OG_RENDERER_VERSION,
    ...fields.map((field) => (field === null || field === undefined ? "" : String(field))),
  ].join("\u0000");
  let hash = 0x811c9dc5;
  for (let index = 0; index < input.length; index++) {
    hash ^= input.charCodeAt(index);
    hash = Math.imul(hash, 0x01000193);
  }
  return (hash >>> 0).toString(16).padStart(8, "0");
}

export type RepoCardData = {
  owner: string;
  name: string;
  description: string | null;
  stars: number;
  forks: number;
  openIssues: number;
  openPulls: number;
  avatarKey: string | null;
  latestRelease: string | null;
};

export type AccountCardData = {
  name: string;