/* Project card component. * 统一 index / projects / search 三处项目卡片的渲染. * options 控制各页面差异 (对齐重构前的三种卡片变体): * - showSubtitle (默认 true): 显示 full_name 副标题 * - showDescription (默认 false): 显示截断描述 (projects 页) * - showForks (默认 true): 显示 🍴 badge * - showStar (默认 true): 显示 ⭐ badge * - showLanguage (默认 true): 显示语言 badge * - showUpdatedAt (默认 false): 显示 "更新于" 行 (projects 页) * - descriptionMaxLen (默认 100) * 点击整卡跳转 /projects/ (与旧内联 onclick 行为一致). */ import { escapeHtml, truncate, formatDate } from "../utils.js"; export function renderProjectCard(p, options = {}) { const { showSubtitle = true, showDescription = false, showForks = true, showStar = true, showLanguage = true, showUpdatedAt = false, descriptionMaxLen = 100, } = options; const projectId = Number.parseInt(p.id, 10); const badges = [ showStar ? `⭐ ${p.stars ?? 0}` : "", showForks ? `🍴 ${p.forks ?? 0}` : "", showLanguage ? `${escapeHtml(p.language || "N/A")}` : "", ] .filter(Boolean) .join(" "); return `
${escapeHtml(p.name)}
${ showSubtitle ? `
${escapeHtml(p.full_name || "")}
` : "" } ${ showDescription ? `

${escapeHtml(truncate(p.description, descriptionMaxLen))}

` : "" }

${badges}

${ showUpdatedAt ? `更新于 ${formatDate(p.updated_at)}` : "" }
`; } /* Delegated click handler; one listener on document covers all cards. */ export function bindProjectCardClicks() { document.addEventListener("click", (e) => { const card = e.target.closest(".project-card[data-project-id]"); if (!card) return; const id = Number.parseInt(card.dataset.projectId, 10); if (!Number.isNaN(id)) location.href = `/projects/${id}`; }); }