--- import HtmlEmbed from "./HtmlEmbed.astro"; interface Props { title: string; // may contain HTML (e.g., ) titleRaw?: string; // plain title for slug/PDF (optional) description?: string; authors?: Array; affiliations?: Array<{ id: number; name: string; url?: string }>; affiliation?: string; // legacy single affiliation published?: string; doi?: string; } const { title, titleRaw, description, authors = [], affiliations = [], affiliation, published, doi } = Astro.props as Props; type Author = { name: string; url?: string; affiliationIndices?: number[] }; function normalizeAuthors(input: Array): Author[] { return (Array.isArray(input) ? input : []) .map((a) => { if (typeof a === 'string') { return { name: a } as Author; } const name = (a?.name ?? '').toString(); const url = (a?.url ?? a?.link) as string | undefined; const affiliationIndices = Array.isArray((a as any)?.affiliationIndices) ? (a as any).affiliationIndices : undefined; return { name, url, affiliationIndices } as Author; }) .filter((a) => a.name && a.name.trim().length > 0); } const normalizedAuthors: Author[] = normalizeAuthors(authors as any); // Determine if affiliation superscripts should be shown (only when there are multiple distinct affiliations referenced by authors) const authorAffiliationIndexSet = new Set(); for (const author of normalizedAuthors) { const indices = Array.isArray(author.affiliationIndices) ? author.affiliationIndices : []; for (const idx of indices) { if (typeof idx === 'number') { authorAffiliationIndexSet.add(idx); } } } const shouldShowAffiliationSupers = authorAffiliationIndexSet.size > 1; const hasMultipleAffiliations = Array.isArray(affiliations) && affiliations.length > 1; function stripHtml(text: string): string { return String(text || '').replace(/<[^>]*>/g, ''); } function slugify(text: string): string { return String(text || '') .normalize('NFKD') .replace(/\p{Diacritic}+/gu, '') .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, '') .slice(0, 120) || 'article'; } const pdfBase = titleRaw ? stripHtml(titleRaw) : stripHtml(title); const pdfFilename = `${slugify(pdfBase)}.pdf`; --- {description && {description}} {normalizedAuthors.length > 0 && ( Author{normalizedAuthors.length > 1 ? 's' : ''} {normalizedAuthors.map((a, i) => { const supers = shouldShowAffiliationSupers && Array.isArray(a.affiliationIndices) && a.affiliationIndices.length ? {a.affiliationIndices.join(',')} : null; return ( {a.url ? {a.name} : a.name}{supers} ); })} )} {(Array.isArray(affiliations) && affiliations.length > 0) && ( Affiliation{affiliations.length > 1 ? 's' : ''} {hasMultipleAffiliations ? ( {affiliations.map((af) => ( {af.url ? {af.name} : af.name} ))} ) : ( {affiliations[0]?.url ? {affiliations[0].name} : affiliations[0]?.name} )} )} {(!affiliations || affiliations.length === 0) && affiliation && ( Affiliation {affiliation} )} {published && ( Published {published} )} PDF Download PDF
{description}
{affiliations[0]?.url ? {affiliations[0].name} : affiliations[0]?.name}
{affiliation}
{published}
Download PDF