export const esc = (value) => String(value ?? "").replace( /[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'", })[c], ); export const number = (value) => Number.isFinite(value) ? value.toLocaleString("zh-CN", { maximumFractionDigits: 1 }) : "—"; export function icon(name, label, attributes = "") { return ``; } export function external(label, url) { return `${esc(label)}`; } export function section(title, body, id = "") { return `

${esc(title)}

${body}
`; } export function table(headings, rows, className = "") { return `
${headings.map((h) => ``).join("")}${rows.join("")}
${esc(h)}
`; } export function empty(message = "没有匹配的数据集", reset = false) { return `

${esc(message)}

${reset ? '' : ""}
`; } export function enhance() { window.lucide?.createIcons(); } export function fact(label, value) { return `
${esc(label)}
${value}
`; } export function tier(id, meta) { const value = meta.tier[id]; return `${esc(id === "-" ? "—" : id)}`; } export function status(id, meta) { return `${esc(meta.status[id]?.name || id)}`; } export function thumbnail(dataset, context) { const preview = context.previews[dataset.id]?.[0]; const figure = context.figures[dataset.id]?.figures?.[0]?.images?.[0]; return preview || figure ? `${esc(dataset.name)}${preview ? ` : ''; } export async function readJSON(path, { optional = false, fallback = {} } = {}) { try { const response = await fetch(path); if (!response.ok) throw new Error(`${path}: ${response.status}`); return await response.json(); } catch (error) { if (!optional) throw error; return fallback; } }