BibliographyBackbone
From Illustrations in German Translations of Mark Twain's Works
Bibliography Generator
Klicke auf den Button, um die Zotero-Einträge von BibliographyData zu laden und als MLA9-formatiertes HTML zu generieren.
<button id="generateBtn" style="
background-color: #008CBA; color: white; padding: 10px 20px; border: none; border-radius: 5px; font-size: 1rem; cursor: pointer; margin-bottom: 1rem;
">Generate Bibliography HTML</button>
Raw HTML Output
Kopiere den kompletten Inhalt und füge ihn in die Bibliography-Seite zwischen den <html>-Tags ein.
<textarea id="bibOutput" style="
width: 100%; height: 700px; font-family: 'Courier New', monospace; font-size: 0.8rem; padding: 10px; border: 2px solid #ddd; border-radius: 5px; box-sizing: border-box; white-space: pre; overflow: auto;
"></textarea>
<script> /**
* Bibliography Generator für Mark Twain Wiki * MLA9-Formatierung mit Tags und Abstracts */
(function() {
'use strict';
async function generateBibliography() {
const output = document.getElementById('bibOutput');
output.value = 'Lade BibliographyData...';
try {
// Fetch JSON
const response = await fetch('/BibliographyData?action=raw');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const entries = await response.json();
// Filtere irrelevante Einträge
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;
});
// Extrahiere alle Tags
const allTags = new Set();
filtered.forEach(entry => {
if (entry.tags && Array.isArray(entry.tags)) {
entry.tags.forEach(tag => allTags.add(tag));
}
});
// Generiere HTML
const html = generateHTML(filtered, Array.from(allTags).sort());
output.value = html;
const status = document.getElementById('bibStatus');
if (status) {
status.textContent = `✓ ${filtered.length} Einträge generiert (${allTags.size} Tags)`;
status.style.color = '#4caf50';
}
} catch (error) {
output.value = `ERROR: ${error.message}`;
output.style.borderColor = '#d32f2f';
}
}
/**
* Generiert komplettes HTML
*/
function generateHTML(entries, allTags) {
const tagSpans = allTags
.map(tag => {
const normalized = tag.toLowerCase().replace(/\s+/g, '_');
return `${escapeHtml(tag)}`;
})
.join('\n ');
const entryHTML = entries
.map((entry, i) => generateBibEntry(entry, i + 1))
.join('\n\n');
return `
${entryHTML}
`;
}
/**
* Generiert einen einzelnen Biblio-Eintrag in MLA9-Format
*/
function generateBibEntry(entry, index) {
const mlaFormatted = formatMLA9(entry);
const tagsAttr = generateTagsAttribute(entry.tags);
const tagSpans = generateTagSpans(entry.tags);
const abstract = entry.abstract ? escapeHtml(entry.abstract) : ;
return `
${mlaFormatted}
${abstract || '(No abstract available)'}
<button class="expand-btn">Show Abstract</button>
`;
}
/**
* Formatiert einen Eintrag in MLA9
* MLA9: Author(s). "Title." Container. Year. Other info.
*/
function formatMLA9(entry) {
let citation = ;
// Autoren
if (entry.authors && entry.authors.length > 0) {
citation += formatAuthors(entry.authors) + '. ';
}
// Titel
if (entry.title) {
// Bücher sind kursiv, Artikel in Anführungszeichen
if (entry.type === 'bookSection' || entry.type === 'book') {
citation += `${escapeHtml(entry.title)}. `;
} else {
citation += `"${escapeHtml(entry.title)}." `;
}
}
// Container (Zeitschrift, Sammelband, etc.)
if (entry.container) {
citation += `${escapeHtml(entry.container)}. `;
}
// Jahr
if (entry.year) {
citation += `${entry.year}. `;
}
// URL
if (entry.url) {
citation += `<a href="${escapeHtml(entry.url)}" target="_blank">${escapeHtml(entry.url)}</a>.`;
} else {
// Entferne den letzten Punkt, falls schon vorhanden
citation = citation.trim();
if (!citation.endsWith('.')) {
citation += '.';
}
}
return citation; }
/**
* Formatiert Autoren
* MLA9: "Last, First, and Last, First"
*/
function formatAuthors(authors) {
if (authors.length === 0) return ;
if (authors.length === 1) {
return formatAuthor(authors[0]);
}
if (authors.length === 2) {
return `${formatAuthor(authors[0])}, and ${formatAuthor(authors[1])}`;
}
// 3+ Autoren: Nur first + et al.
return `${formatAuthor(authors[0])}, et al.`;
}
/**
* Formatiert einen einzelnen Autor
*/
function formatAuthor(author) {
if (!author) return ;
const family = author.family || ;
const given = author.given || ;
if (!family) return given; if (!given) return family;
return `${family}, ${given}`;
}
/**
* Generiert data-tags Attribut
*/
function generateTagsAttribute(tags) {
if (!tags || tags.length === 0) return ;
const normalized = tags
.map(tag => tag.toLowerCase().replace(/\s+/g, '_'))
.join(' ');
return ` data-tags="${normalized}"`;
}
/**
* Generiert Tag-Spans
*/
function generateTagSpans(tags) {
if (!tags || tags.length === 0) return ;
return tags
.map(tag => {
const normalized = tag.toLowerCase().replace(/\s+/g, '_');
return `${escapeHtml(tag)}`;
})
.join();
}
/**
* HTML-Escape
*/
function escapeHtml(text) {
if (!text) return ;
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, m => map[m]);
}
/**
* Initialisierung
*/
function init() {
const btn = document.getElementById('generateBtn');
if (btn) {
btn.addEventListener('click', generateBibliography);
console.log('Bibliography Generator bereit');
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})(); </script>