thibaud frere
fix footer numbers | fix footer title | fix pdf
0268a3e
---
interface Props {
citationText: string;
bibtex: string;
licence?: string;
doi?: string;
}
const { citationText, bibtex, licence, doi } = Astro.props as Props;
---
<footer class="footer">
<div class="footer-inner">
<section class="citation-block">
<h3>Citation</h3>
<p>For attribution in academic contexts, please cite this work as</p>
<pre class="citation short">{citationText}</pre>
<p>BibTeX citation</p>
<pre class="citation long">{bibtex}</pre>
</section>
{doi && (
<section class="doi-block">
<h3>DOI</h3>
<p><a href={`https://doi.org/${doi}`} target="_blank" rel="noopener noreferrer">{doi}</a></p>
</section>
)}
{licence && (
<section class="reuse-block">
<h3>Reuse</h3>
<p set:html={licence}></p>
</section>
)}
<section class="references-block">
<slot />
</section>
</div>
</footer>
<script is:inline>
(() => {
const getFooter = () => document.currentScript?.closest('footer') || document.querySelector('footer.footer');
const footer = getFooter();
if (!footer) return;
const target = footer.querySelector('.references-block');
if (!target) return;
const contentRoot = document.querySelector('section.content-grid main') || document.querySelector('main') || document.body;
const ensureHeading = (text) => {
const exists = Array.from(target.children).some((c) => c.tagName === 'H3' && c.textContent.trim().toLowerCase() === text.toLowerCase());
if (!exists) {
const h = document.createElement('h3');
h.textContent = text;
target.appendChild(h);
}
};
const moveIntoFooter = (element, headingText) => {
if (!element) return false;
// Remove an eventual heading already included inside the block (avoid duplicates)
const firstHeading = element.querySelector(':scope > h1, :scope > h2, :scope > h3');
if (firstHeading) {
const txt = (firstHeading.textContent || '').trim().toLowerCase();
const targetTxt = headingText.trim().toLowerCase();
if (txt === targetTxt || txt.includes('reference') || txt.includes('bibliograph')) {
firstHeading.remove();
}
}
ensureHeading(headingText);
target.appendChild(element);
return true;
};
const run = () => {
const findFirstOutsideFooter = (selectors) => {
for (const sel of selectors) {
const el = contentRoot.querySelector(sel);
if (el && !footer.contains(el)) return el;
}
return null;
};
const referencesEl = findFirstOutsideFooter(['#references', '.references', '.bibliography']);
const footnotesEl = findFirstOutsideFooter(['.footnotes']);
const movedRefs = moveIntoFooter(referencesEl, 'References');
const movedNotes = moveIntoFooter(footnotesEl, 'Footnotes');
return movedRefs || movedNotes;
};
// Try now; if not found yet, try again on DOM ready
const done = run();
if (!done) {
const onReady = () => run();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', onReady, { once: true });
} else {
setTimeout(onReady, 0);
}
}
// Resize on window changes (e.g., fonts, layout)
// No textarea auto-resize needed for <pre> blocks
})();
</script>
<style is:global>
.footer {
contain: layout style;
font-size: 0.8em;
line-height: 1.7em;
margin-top: 60px;
margin-bottom: 0;
border-top: 1px solid rgba(0, 0, 0, 0.1);
color: rgba(0, 0, 0, 0.5);
}
.footer-inner {
max-width: 1280px;
margin: 0 auto;
padding: 60px 16px 48px;
display: grid;
grid-template-columns: 220px minmax(0, 680px) 260px;
gap: 32px;
align-items: start;
}
/* Use the parent grid (3 columns like .content-grid) */
.citation-block,
.references-block,
.reuse-block,
.doi-block {
display: contents;
}
.citation-block > h3,
.references-block > h3,
.reuse-block > h3,
.doi-block > h3 {
grid-column: 1;
font-size: 15px;
margin: 0;
text-align: right;
padding-right: 30px;
}
.citation-block > :not(h3),
.references-block > :not(h3),
.reuse-block > :not(h3),
.doi-block > :not(h3) {
grid-column: 2;
}
.citation-block h3 {
margin: 0 0 8px;
}
.citation-block h4 {
margin: 16px 0 8px;
font-size: 14px;
text-transform: uppercase;
color: var(--muted-color);
}
.citation-block p,
.reuse-block p,
.doi-block p,
.footnotes ol,
.footnotes ol p,
.references {
margin-top: 0;
}
/* Distill-like appendix citation styling */
.citation {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 11px;
line-height: 15px;
border-left: 1px solid rgba(0, 0, 0, 0.1);
padding-left: 18px;
border: 1px solid rgba(0,0,0,0.1);
background: rgba(0, 0, 0, 0.02);
padding: 10px 18px;
border-radius: 3px;
color: rgba(150, 150, 150, 1);
overflow: hidden;
margin-top: -12px;
white-space: pre-wrap;
word-wrap: break-word;
}
.citation a {
color: rgba(0, 0, 0, 0.6);
text-decoration: underline;
}
.citation.short {
margin-top: -4px;
}
.references-block h3 {
margin: 0;
}
/* Distill-like list styling for references/footnotes */
.references-block ol {
padding: 0 0 0 15px;
}
@media (min-width: 768px) {
.references-block ol {
padding: 0 0 0 30px;
margin-left: -30px;
}
}
.references-block li {
margin-bottom: 1em;
}
/* Évite le double affichage des numéros: masque le marqueur natif */
.references-block li::marker {
content: '';
}
.references-block a {
color: var(--text-color);
}
[data-theme="dark"] .footer { border-top-color: rgba(255,255,255,.15); color: rgba(200,200,200,.8); }
[data-theme="dark"] .citation { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,.15); color: rgba(200,200,200,1); }
[data-theme="dark"] .citation a { color: rgba(255,255,255,0.75); }
/* Footer links: use primary color consistently */
.footer a {
color: var(--primary-color);
border-bottom: 1px solid var(--link-underline);
text-decoration: none;
}
.footer a:hover {
color: var(--primary-color-hover);
border-bottom-color: var(--link-underline-hover);
}
[data-theme="dark"] .footer a {
color: var(--primary-color);
}
</style>