Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/_default/params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ github_project_repo: https://github.com/interlisp/medley
# gcs_engine_id: search engine
gcs_engine_id: 33ef4cbe0703b4f3a

# Zotero Group ID for bibliography management
zotero_group_id: 2914042

# Footer Links
#
# user: End user relevant links. These will show up on
Expand Down
209 changes: 206 additions & 3 deletions layouts/bibliography/single.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ <h1>{{ .Title }}</h1>
{{ end }}
<br>
</p>

<p>
<strong>Abstract</strong>
<br>
Expand Down Expand Up @@ -209,13 +210,215 @@ <h1>{{ .Title }}</h1>
{{ end }}
</p>
<p>
{{- if .Params.zotero_url }}
<a href="{{ .Params.zotero_url | safeURL }}" target="_blank" rel="noopener noreferrer">View on Zotero</a>
{{- end -}}
{{- if .Params.zotero_url }}
<a class="btn btn-primary btn-sm"
href="{{ .Params.zotero_url | safeURL }}"
target="_blank" rel="noopener noreferrer">View on Zotero</a>
{{- end -}}

<!-- Citation -->
{{/* Build Zotero API params (group id + item key + style) */}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lines that are only Hugo operations should have {{- & -}} delimiters so whitespace between them is stripped from the output. (Generally, no functional effect, but helps with readability if looking at "page source" in the browser. Also, smaller pages.

{{ $gid := site.Params.zotero_group_id }}

{{ $key := .File.TranslationBaseName }}

{{ $style := or site.Params.zotero.style "apa" }}

{{ if and $gid $key }}
<button type="button" id="citeBtn"
class="btn btn-primary btn-sm"
data-gid="{{ $gid }}"
data-key="{{ $key }}"
data-style="{{ $style }}">
Citation
</button>
{{ end }}
</p>

<div class="summary">
{{ .Content }}
</div>
</article>
<!-- Citation modal -->
<div id="citationModal" class="citation-modal" hidden>
<div class="citation-dialog">
<div class="citation-header">
<strong>Citation</strong>
<button type="button" class="citation-close" aria-label="Close">×</button>
</div>

<!-- Tabs -->
<div class="citation-tabs" role="tablist" aria-label="Citation views">
<button type="button" class="tab-btn is-active" data-tab="formatted" role="tab" aria-selected="true" aria-controls="tab-formatted">Formatted</button>
<button type="button" class="tab-btn" data-tab="raw" role="tab" aria-selected="false" aria-controls="tab-raw">HTML</button>
</div>

<div class="citation-body">
<!-- Formatted view -->
<div id="tab-formatted" class="tab-panel is-active" role="tabpanel" aria-labelledby="tabbtn-formatted">
<div id="citationContent">Loading…</div>
</div>

<!-- Raw HTML view -->
<div id="tab-raw" class="tab-panel" role="tabpanel" aria-labelledby="tabbtn-raw">
<pre class="codebox"><code id="citationRaw" class="language-html"></code></pre>
</div>
</div>

<div class="citation-actions">
<button type="button" id="copyCitation">Copy Text</button>
<button type="button" id="copyCitationHtml">Copy HTML</button>
<button type="button" class="citation-close">Close</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "Close" is a larger font, and no border, compared to the two buttons adjacent.

</div>
</div>
<div class="citation-backdrop"></div>
</div>


<style>
.citation-modal[hidden] { display: none; }
.citation-modal { position: fixed; inset: 0; z-index: 1050; }
.citation-dialog {
position: absolute; top: 10%; left: 50%; transform: translateX(-50%);
max-width: 720px; width: calc(100% - 2rem);
background: #fff; border-radius: 6px; box-shadow: 0 10px 30px rgba(0,0,0,.2);
overflow: hidden;
}
.citation-header { display:flex; justify-content:space-between; align-items:center; padding:.75rem 1rem; border-bottom:1px solid #eee; }
.citation-close { background:none; border:0; font-size:1.25rem; line-height:1; cursor:pointer; }
.citation-tabs { display:flex; gap:.25rem; padding:.5rem 1rem; border-bottom:1px solid #eee; }
.tab-btn {
border: 1px solid #ddd; background:#f8f9fa; border-radius:4px; padding:.35rem .6rem; cursor:pointer;
}
.tab-btn.is-active { background:#fff; border-color:#bbb; }
.citation-body { padding:1rem; max-height:50vh; overflow:auto; }
#citationContent { font-size:1rem; line-height:1.4; }
.codebox {
background:#f6f8fa; border:1px solid #e1e4e8; border-radius:6px;
padding:.75rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size:.9rem; line-height:1.4; white-space:pre-wrap; word-break:break-word;
}
.tab-panel { display:none; }
.tab-panel.is-active { display:block; }
.citation-actions { display:flex; gap:.5rem; justify-content:flex-end; padding:.75rem 1rem; border-top:1px solid #eee; }
</style>

<script src="{{ "js/vendor/prettier/standalone.js" | relURL }}" defer></script>
<script src="{{ "js/vendor/prettier/plugins/html.js" | relURL }}" defer></script>

<script>
(function () {
const modal = document.getElementById('citationModal');
const contentBox = document.getElementById('citationContent');
const rawBox = document.getElementById('citationRaw');

function openModal() { modal.hidden = false; }
function closeModal() { modal.hidden = true; }

function setActiveTab(name) {
document.querySelectorAll('.tab-btn').forEach(btn => {
const isActive = btn.dataset.tab === name;
btn.classList.toggle('is-active', isActive);
btn.setAttribute('aria-selected', isActive ? 'true' : 'false');
});
document.querySelectorAll('.tab-panel').forEach(panel => {
const isActive = panel.id === ('tab-' + name);
panel.classList.toggle('is-active', isActive);
});
}

function copyTextToClipboard(text, button) {
const done = () => {
if (button) {
const original = button.textContent;
button.textContent = 'Copied';
setTimeout(() => (button.textContent = original), 1200);
}
};
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(done).catch(done);
} else {
const ta = document.createElement('textarea');
ta.value = text; document.body.appendChild(ta);
ta.select(); try { document.execCommand('copy'); } catch(e) {}
document.body.removeChild(ta); done();
}
}

document.addEventListener('click', function (e) {
// Open + fetch
if (e.target.matches('#citeBtn')) {
e.preventDefault();
const btn = e.target;
const gid = btn.dataset.gid;
const key = btn.dataset.key;
const style = btn.dataset.style || 'apa';
// Use Zotero API; format=bib returns HTML bibliography item(s)
const url = `https://api.zotero.org/groups/${encodeURIComponent(gid)}/items/${encodeURIComponent(key)}?format=bib&style=${encodeURIComponent(style)}&linkwrap=1`;

contentBox.textContent = 'Loading…';
rawBox.textContent = '';
setActiveTab('formatted');
openModal();

fetch(url, { headers: { 'Accept': 'text/html' }})
.then(r => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.text();
})
.then(html => {
contentBox.innerHTML = html;
try {
const formatted = window.prettier.format(html, { parser: "html", plugins: window.prettierPlugins, tabWidth: 2 });
// prettier.format may return a string or a Promise depending on plugin loading; normalize to a Promise
return Promise.resolve(formatted).then(pretty => {
rawBox.textContent = pretty;
return html;
});
} catch (err) {
// synchronous error formatting
rawBox.textContent = String(err);
return html;
}
})
.catch(err => {
const msg = `Failed to load citation (${err})`;
contentBox.textContent = msg;
rawBox.textContent = msg;
});
}

// Close
if (e.target.matches('.citation-close')) {
e.preventDefault();
closeModal();
}

// Copy buttons
if (e.target.matches('#copyCitation')) {
e.preventDefault();
copyTextToClipboard(contentBox.innerText.trim(), e.target);
}
if (e.target.matches('#copyCitationHtml')) {
e.preventDefault();
copyTextToClipboard(rawBox.textContent.trim(), e.target);
}

// Tabs
if (e.target.matches('.tab-btn')) {
e.preventDefault();
setActiveTab(e.target.dataset.tab);
}
});

// Close when clicking backdrop or pressing Escape
modal.addEventListener('click', function (e) {
if (e.target.classList.contains('citation-backdrop')) closeModal();
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') closeModal();
});
})();
</script>

{{ end }}
Loading