|
|
| Line 37: |
Line 37: |
|
| |
|
| <script> | | <script> |
| /**
| | <script> |
| * Bibliography Generator für Mark Twain Wiki
| | console.log('Script wird geladen...'); |
| * MLA9-Formatierung mit Tags und Abstracts
| |
| */
| |
|
| |
|
| (function() {
| | document.addEventListener('DOMContentLoaded', function() { |
| 'use strict';
| | console.log('DOM ist bereit'); |
| | | const btn = document.getElementById('generateBtn'); |
| async function generateBibliography() {
| | console.log('Button gefunden?', btn); |
| const output = document.getElementById('bibOutput');
| | |
| output.value = 'Lade BibliographyData...';
| | if (btn) { |
| | | console.log('Event Listener wird hinzugefügt...'); |
| try {
| | btn.addEventListener('click', function() { |
| // Fetch JSON
| | console.log('Button wurde geklickt!'); |
| const response = await fetch('/BibliographyData?action=raw');
| | alert('Button funktioniert!'); |
| 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 `<span class="tag" data-tag="${normalized}">${escapeHtml(tag)}</span>`;
| |
| })
| |
| .join('\n ');
| |
| | |
| const entryHTML = entries
| |
| .map((entry, i) => generateBibEntry(entry, i + 1))
| |
| .join('\n\n');
| |
| | |
| return `<div class="bib-tags">
| |
| ${tagSpans} | |
| </div>
| |
| | |
| <div id="listView" class="bibliography">
| |
| ${entryHTML}
| |
| </div>
| |
| | |
| <div id="networkView" class="network hidden"></div>`;
| |
| } | |
| | |
| /**
| |
| * 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 `<!-- ${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>`;
| |
| }
| |
| | |
| /**
| |
| * 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 += `<i>${escapeHtml(entry.title)}</i>. `;
| |
| } else {
| |
| citation += `"${escapeHtml(entry.title)}." `;
| |
| }
| |
| } | |
| | |
| // Container (Zeitschrift, Sammelband, etc.)
| |
| if (entry.container) {
| |
| citation += `<i>${escapeHtml(entry.container)}</i>. `;
| |
| }
| |
| | |
| // 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 `<span class="tag" data-tag="${normalized}">${escapeHtml(tag)}</span>`;
| |
| })
| |
| .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> | | </script> |
| </html> | | </html> |
Klicke auf den Button, um die Zotero-Einträge von BibliographyData zu laden und als MLA9-formatiertes HTML zu generieren.
Raw HTML Output
Kopiere den kompletten Inhalt und füge ihn in die Bibliography-Seite zwischen den <html>-Tags ein.