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 ``;
}
export function table(headings, rows, className = "") {
return `
`;
}
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
? `
`
: '';
}
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;
}
}