BibliographyBackbone

From Illustrations in German Translations of Mark Twain's Works

Revision as of 00:25, 12 May 2026 by HMHTEST (talk | contribs)

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 `

 ${tagSpans}

${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}

   ${tagSpans}

${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>