File size: 3,481 Bytes
72cfb5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33aefb9
72cfb5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8e1b6c
72cfb5a
 
 
 
 
 
 
 
 
 
 
33aefb9
72cfb5a
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
---
import HtmlEmbed from "./HtmlEmbed.astro";

interface Props {
  title: string; // may contain HTML (e.g., <br/>)
  titleRaw?: string; // plain title for slug/PDF (optional)
  description?: string;
  authors?: string[];
  affiliation?: string;
  published?: string;
}

const { title, titleRaw, description, authors = [], affiliation, published } = Astro.props as Props;

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 ? titleRaw : stripHtml(title);
const pdfFilename = `${slugify(pdfBase)}.pdf`;
---
<section class="hero">
  <h1 class="hero-title" set:html={title}></h1>
  <div class="hero-banner">
    <HtmlEmbed src="banner.html" frameless />
    {description && <p class="hero-desc">{description}</p>}
  </div>
</section>

<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 meta-container-cell--pdf">
      <h3>PDF</h3>
      <p><button id="download-pdf-btn" data-pdf-filename={pdfFilename}>Download PDF</button></p>
    </div>
  </div>
</header>

<script>
  // Attach a handler to trigger a programmatic download
  (() => {
    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>

<style>
  /* Hero (full-width) */
  .hero { width: 100%; padding: 48px 16px 16px; text-align: center; }
  .hero-title { font-size: clamp(28px, 4vw, 48px); font-weight: 800; line-height: 1.1; margin: 0 0 8px; max-width: 60%; margin: auto; }
  .hero-banner { max-width: 980px; margin: 0 auto; }
  .hero-desc { color: var(--muted-color); font-style: italic; margin: 0 0 16px 0; }

  /* Meta (byline-like header) */
  .meta { border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); padding: 1rem 0; font-size: 0.9rem; line-height: 1.8em; }
  .meta-container { max-width: 720px; display: flex; flex-direction: row; justify-content: space-between; margin: 0 auto; gap: 8px; }
  .meta-container-cell { display: flex; flex-direction: column; gap: 8px; }
  .meta-container-cell h3 { margin: 0; font-size: 12px; font-weight: 400; color: var(--muted-color); text-transform: uppercase; letter-spacing: .02em; }
  .meta-container-cell p { margin: 0; }
  @media print { .meta-container-cell--pdf { display: none !important; } }
</style>