BibliographyBackbone: Difference between revisions
From Illustrations in German Translations of Mark Twain's Works
No edit summary |
No edit summary |
||
| (11 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
{{Seitenkopf|Bibliography Generator}} | {{Seitenkopf|Bibliography Generator}} | ||
<html> | <html> | ||
<div style="max-width: 1000px;"> | |||
<div style="max-width: 1000px | |||
<button id="generateBtn" style=" | <button id="generateBtn" style=" | ||
| Line 18: | Line 14: | ||
margin-bottom: 1rem; | margin-bottom: 1rem; | ||
">Generate Bibliography HTML</button> | ">Generate Bibliography HTML</button> | ||
<textarea id="bibOutput" style=" | <textarea id="bibOutput" style=" | ||
width: 100%; | width: 100%; | ||
height: | height: 400px; | ||
font-family: 'Courier New', monospace; | font-family: 'Courier New', monospace; | ||
font-size: 0. | font-size: 0.85rem; | ||
padding: 10px; | padding: 10px; | ||
border: 2px solid #ddd; | border: 2px solid #ddd; | ||
| Line 37: | Line 28: | ||
"></textarea> | "></textarea> | ||
<script> | |||
(function() { | |||
function escapeHtml(text) { | |||
if (!text) return ''; | |||
const map = { | |||
'&': '&', | |||
'<': '<', | |||
'>': '>', | |||
'"': '"', | |||
"'": ''' | |||
}; | |||
return text.replace(/[&<>"']/g, m => map[m]); | |||
} | |||
function getOrUnknown(value) { | |||
if (!value || (typeof value === 'string' && !value.trim())) { | |||
return 'unknown'; | |||
} | |||
return value; | |||
} | |||
function formatAuthors(authors) { | |||
if (!authors || authors.length === 0) { | |||
return 'unknown'; | |||
} | |||
if (authors.length === 1) { | |||
const a = authors[0]; | |||
const family = a.family || 'unknown'; | |||
const given = a.given || ''; | |||
return given ? `${family}, ${given}` : family; | |||
} | |||
if (authors.length === 2) { | |||
const a1 = authors[0]; | |||
const a2 = authors[1]; | |||
const name1 = (a1.family || 'unknown') + (a1.given ? ', ' + a1.given : ''); | |||
const name2 = (a2.family || 'unknown') + (a2.given ? ', ' + a2.given : ''); | |||
return `${name1}, and ${name2}`; | |||
} | |||
const a = authors[0]; | |||
const name = (a.family || 'unknown') + (a.given ? ', ' + a.given : ''); | |||
return `${name}, et al.`; | |||
} | |||
function formatMLA9(entry) { | |||
let citation = ''; | |||
const authors = formatAuthors(entry.authors); | |||
citation += authors + '. '; | |||
const title = getOrUnknown(entry.title); | |||
if (entry.type === 'bookSection' || entry.type === 'book') { | |||
citation += `<i>${escapeHtml(title)}</i>. `; | |||
} else { | |||
citation += `"${escapeHtml(title)}." `; | |||
} | |||
const container = entry.container; | |||
if (container && container.trim()) { | |||
citation += `<i>${escapeHtml(container)}</i>. `; | |||
} | |||
const year = getOrUnknown(entry.year); | |||
citation += `${year}. `; | |||
if (entry.url && entry.url.trim()) { | |||
citation += `<a href="${escapeHtml(entry.url)}" target="_blank">${escapeHtml(entry.url)}</a>.`; | |||
} else { | |||
citation = citation.trim(); | |||
if (!citation.endsWith('.')) { | |||
citation += '.'; | |||
} | |||
} | |||
return citation; | |||
} | |||
function generateTagsAttribute(tags) { | |||
if (!tags || tags.length === 0) { | |||
return ' data-tags="untagged"'; | |||
} | |||
const normalized = tags | |||
.map(tag => tag.toLowerCase().replace(/\s+/g, '_')) | |||
.join(' '); | |||
return ` data-tags="${normalized}"`; | |||
} | |||
function generateTagSpans(tags) { | |||
if (!tags || tags.length === 0) { | |||
return '<span class="tag" data-tag="untagged">untagged</span>'; | |||
} | |||
return tags | |||
.map(tag => { | |||
const normalized = tag.toLowerCase().replace(/\s+/g, '_'); | |||
return `<span class="tag" data-tag="${normalized}">${escapeHtml(tag)}</span>`; | |||
}) | |||
.join('\n '); | |||
} | |||
function generateBibEntry(entry, index) { | |||
const mlaFormatted = formatMLA9(entry); | |||
const tagsAttr = generateTagsAttribute(entry.tags); | |||
const tagSpans = generateTagSpans(entry.tags); | |||
const abstract = entry.abstract && entry.abstract.trim() ? escapeHtml(entry.abstract) : ''; | |||
return `<!-- ${index} --> | |||
<div class="bib-entry"${tagsAttr}> | |||
<h3>${mlaFormatted}</h3> | |||
<div class="bib-tags"> | |||
${tagSpans} | |||
</div> | |||
<p class="short-abstract">${abstract || '(No abstract available)'}</p> | |||
<button class="expand-btn">Show Abstract</button> | |||
<div class="abstract hidden"> | |||
<p>${abstract || 'No abstract available.'}</p> | |||
</div> | |||
</div>`; | |||
} | |||
async function generateBibliography() { | |||
const output = document.getElementById('bibOutput'); | |||
output.value = 'Lade Daten...'; | |||
try { | |||
const response = await fetch('/BibliographyData?action=raw'); | |||
if (!response.ok) throw new Error(`HTTP ${response.status}`); | |||
const entries = await response.json(); | |||
const filtered = entries.filter(entry => { | |||
if (entry.tags && entry.tags.includes('Not relevant for Mark Twain')) { | |||
return false; | |||
} | |||
if (!entry.title || entry.title.trim() === 'Untitled') { | |||
return false; | |||
} | |||
return true; | |||
}); | |||
const allTags = new Set(); | |||
filtered.forEach(entry => { | |||
if (entry.tags && Array.isArray(entry.tags)) { | |||
entry.tags.forEach(tag => allTags.add(tag)); | |||
} | |||
}); | |||
const tagSpans = Array.from(allTags) | |||
.sort() | |||
.map(tag => { | |||
const normalized = tag.toLowerCase().replace(/\s+/g, '_'); | |||
return `<span class="tag" data-tag="${normalized}">${escapeHtml(tag)}</span>`; | |||
}) | |||
.join('\n '); | |||
const entryHTML = filtered | |||
.map((entry, i) => generateBibEntry(entry, i + 1)) | |||
.join('\n\n'); | |||
const html = `<div class="bib-tags"> | |||
${tagSpans} | |||
</div> | </div> | ||
< | <div id="listView" class="bibliography"> | ||
${entryHTML} | |||
</div> | |||
<div id="networkView" class="network hidden"></div>`; | |||
output.value = html; | |||
} catch (error) { | |||
output.value = 'ERROR: ' + error.message; | |||
} | |||
} | |||
const btn = document.getElementById('generateBtn'); | const btn = document.getElementById('generateBtn'); | ||
if (btn | if (btn) { | ||
btn.addEventListener('click', | btn.addEventListener('click', generateBibliography); | ||
} | } | ||
}); | })(); | ||
</script> | </script> | ||
</div> | |||
</html> | </html> | ||
Latest revision as of 00:51, 12 May 2026
Bibliography Generator