| | --- |
| | interface Props { |
| | title: string; |
| | authors?: string[]; |
| | affiliation?: string; |
| | published?: string; |
| | } |
| | const { title, authors = [], affiliation, published } = Astro.props as Props; |
| | 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 pdfFilename = `${slugify(title)}.pdf`; |
| | --- |
| | <header class="meta"> |
| | <div class="meta-container"> |
| | {authors.length > 0 && ( |
| | <div class="meta-container-cell"> |
| | <h3>Authors</h3> |
| | <p>{authors.join(', ')}</p> |
| | </div> |
| | )} |
| | {affiliation && ( |
| | <div class="meta-container-cell"> |
| | <h3>Affiliation</h3> |
| | <p>{affiliation}</p> |
| | </div> |
| | )} |
| | {published && ( |
| | <div class="meta-container-cell"> |
| | <h3>Published</h3> |
| | <p>{published}</p> |
| | </div> |
| | )} |
| | <div class="meta-container-cell"> |
| | <h3>PDF</h3> |
| | <p><button id="download-pdf-btn" data-pdf-filename={pdfFilename}>Download PDF</button></p> |
| | </div> |
| | </div> |
| | </header> |
| |
|
| | <script> |
| | |
| | (() => { |
| | const ready = () => { |
| | const btn = document.getElementById('download-pdf-btn'); |
| | if (!btn) return; |
| | btn.addEventListener('click', () => { |
| | const a = document.createElement('a'); |
| | const pdf = btn.getAttribute('data-pdf-filename') || 'article.pdf'; |
| | a.href = `/${pdf}`; |
| | a.setAttribute('download', pdf); |
| | document.body.appendChild(a); |
| | a.click(); |
| | a.remove(); |
| | }); |
| | }; |
| | if (document.readyState === 'loading') { |
| | document.addEventListener('DOMContentLoaded', ready, { once: true }); |
| | } else { ready(); } |
| | })(); |
| | </script> |
| |
|
| |
|