|
|
--- |
|
|
interface Props { |
|
|
citationText: string; |
|
|
bibtex: string; |
|
|
licence?: string; |
|
|
doi?: string; |
|
|
acknowledgements?: string; |
|
|
} |
|
|
const { citationText, bibtex, licence, doi, acknowledgements } = Astro.props as Props; |
|
|
--- |
|
|
<footer class="footer"> |
|
|
<div class="footer-inner"> |
|
|
<section class="citation-block"> |
|
|
<h3>Citation</h3> |
|
|
<p>For attribution, cite this work as</p> |
|
|
<pre class="citation short">{citationText}</pre> |
|
|
|
|
|
<p>BibTeX citation</p> |
|
|
<pre class="citation long">{bibtex}</pre> |
|
|
</section> |
|
|
{acknowledgements && ( |
|
|
<section class="acknowledgements-block"> |
|
|
<h3>Acknowledgements</h3> |
|
|
<p set:html={acknowledgements}></p> |
|
|
</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; |
|
|
|
|
|
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; |
|
|
}; |
|
|
|
|
|
|
|
|
const done = run(); |
|
|
if (!done) { |
|
|
const onReady = () => run(); |
|
|
if (document.readyState === 'loading') { |
|
|
document.addEventListener('DOMContentLoaded', onReady, { once: true }); |
|
|
} else { |
|
|
setTimeout(onReady, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
})(); |
|
|
</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; |
|
|
} |
|
|
|
|
|
|
|
|
.citation-block, |
|
|
.acknowledgements-block, |
|
|
.references-block, |
|
|
.reuse-block, |
|
|
.doi-block { |
|
|
display: contents; |
|
|
} |
|
|
|
|
|
.citation-block > h3, |
|
|
.acknowledgements-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), |
|
|
.acknowledgements-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, |
|
|
.acknowledgements-block p, |
|
|
.reuse-block p, |
|
|
.doi-block p, |
|
|
.footnotes ol, |
|
|
.footnotes ol p, |
|
|
.references { |
|
|
margin-top: 0; |
|
|
} |
|
|
|
|
|
|
|
|
.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; |
|
|
} |
|
|
|
|
|
|
|
|
.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; |
|
|
} |
|
|
|
|
|
.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 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> |
|
|
|