1// Search indexes, compact JSON that site/assets/search.ts fetches the first2// time the search opens. Per repo: commits, reviews and wiki pages; file paths3// come from the default branch's file list, already emitted for the finder.4// For the forge: repo names and descriptions. Bodies and wiki text are capped5// to keep the files small. File contents are in the code index6// (lib/code-index.ts), which `code` points at when the default branch has one.7import type { Repo, RepoSummary } from './types.ts';89const BODY = 240;10const WIKI = 2000;1112const ENTITIES: Record<string, string> = { amp: '&', lt: '<', gt: '>', quot: '"', '#39': "'" };13const flat = (s: string, n: number): string => s.replace(/\s+/g, ' ').trim().slice(0, n);14// A wiki page as the plain text a reader sees, without its title. Block tags15// end in newlines, so dropping the tags keeps words apart.16function plain(w: { html: string; title: string }): string {17 const text = flat(w.html.replace(/<[^>]*>/g, '').replace(/&(amp|lt|gt|quot|#39);/g, (_, e: string) => ENTITIES[e]), Infinity);18 return (text.startsWith(w.title) ? text.slice(w.title.length) : text).trim();19}2021export function repoIndex(repo: Repo, code: string | null = null): string {22 const u = repo.urls;23 const commits = [...repo.commits.values()]24 .sort((a, b) => Date.parse(b.author.date) - Date.parse(a.author.date))25 .map((c) => [c.sha, c.subject, c.author.name, c.author.date.slice(0, 10), flat(c.body, BODY)]);26 const reviews = [...repo.reviews].reverse().map((r) => [r.id, r.title, r.branch, r.author ?? '', r.status]);27 const wiki = repo.wiki.map((w) => [u.wiki(w.slug).href, w.title, plain(w).slice(0, WIKI)]);28 const files = repo.trees.has(repo.defaultBranch) ? u.files(repo.defaultBranch).href : null;29 return JSON.stringify({ blob: u.blobBase(repo.defaultBranch).href, files, code, commits, reviews, wiki, home: u.home.href });30}3132export function reposIndex(repos: RepoSummary[]): string {33 return JSON.stringify({ repos: repos.map((s) => [s.slug, s.description, s.urls.home.href]) });34}