Skip to content
Snippets Groups Projects
makeSources.tsx 9.78 KiB
Newer Older
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
import React, { useState, useEffect } from "react";
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
import bibtexParse from 'bibtex-parser-js';

interface BibEntry {
  ENTRYTYPE: string;
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  TITLE?: string;
  AUTHOR?: string;
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  journal?: string;
  volume?: string;
  pages?: string;
  year?: string;
  doi?: string;
  [key: string]: any;
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
interface BibtexParserProps {
  bibtexSources: string[]; // Accept an array of BibTeX strings
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  special?: string,
  start?: number
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
}
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

function formatPages(pages: string | undefined): JSX.Element | null {
    // Check if pages is provided and is a non-empty string
    if (pages && pages.length > 0) {
        // Check for common page range separators
        const pageRangeRegex = /--|-|–|–/; // RegEx to match various dash types
        if (pageRangeRegex.test(pages)) {
            const pag = pages.split(pageRangeRegex).map(p => p.trim());
            const begin = pag[0];
            const end = pag[1];

            // Return formatted JSX
            return (
                <>
                    ,&nbsp;<span property="schema:pageBegin">{begin}</span>-<span property="schema:pageEnd">{end}</span>
                </>
            );
        } else if (/^\d+(-\d+)?$/.test(pages)) {
            // If pages is a single numeric range, return it directly
            return (
                <>
                ,&nbsp;<span property="schema:pageBegin">{pages}</span>
                </>
            );
        } else {
            // Handle non-numeric page info
            console.warn(`Non-numeric page information detected ('${pages}'). Treating as missing.`);
            return null; // Return null if invalid
        }
    } else {
        console.warn("Sorry, no page information.");
        return null; // Return null if no page info
    }
}


Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
export const BibtexParser: React.FC<BibtexParserProps> = ({ bibtexSources , special, start}) => {
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  const [parsedEntries, setParsedEntries] = useState<BibEntry[]>([]);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  // Parse BibTeX on component mount or when sources change
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  useEffect(() => {
    //console.log("Parsing BibTeX sources: ", bibtexSources);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    try {
      const allEntries: BibEntry[] = [];
      bibtexSources.forEach((bibtex) => {
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
       // console.log(`Parsing BibTeX entry #${index + 1}: `, bibtex);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
        const parsed = bibtexParse.toJSON(bibtex);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
       // console.log(`Parsed entry: `, parsed);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
        allEntries.push(...parsed);
      });
      setParsedEntries(allEntries);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      //console.log("All parsed entries: ", allEntries);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    } catch (error) {
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
     console.error("Error parsing BibTeX: ", error);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      alert("An error occurred while parsing the BibTeX entries. Please check the format." + bibtexSources);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    }
  }, [bibtexSources]);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

  // Helper function to render AUTHORS
  const formatAuthors = (authors: string): string => {
    //console.log("Original input:", authors);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

    // Bereinigen des Eingabestrings und Ersetzen von "and" durch "|"
    const cleanedAuthors = authors
        .replace(/\s*and\s*/g, "|") // "and" durch "|" ersetzen
        .replace(/\{|\}/g, "")      // geschweifte Klammern entfernen
        .trim();
    
    //console.log("Cleaned authors string:", cleanedAuthors);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

    // Autoren in ein Array aufteilen
    const authorList = cleanedAuthors.split("|").map(author => author.trim());
    //console.log("Split author list:", authorList);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

    // Maximale Anzahl der anzuzeigenden Autoren
    const maxAuthors = 7;

    // Formatiere jeden Autor
    const formattedAuthors = authorList.map((author, _index) => {
        //console.log(`Processing author #${index + 1}:`, author);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

        // Nachname und Vornamen aufteilen
        const [last, firstNames] = author.includes(",") ? 
            author.split(",").map(part => part.trim()) :
            ['', author]; // Wenn kein Komma vorhanden ist, wird der gesamte Name als Vorname behandelt

       // console.log(`Last name: "${last}", First names: "${firstNames}"`);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

        // Initialen für Vornamen erstellen
        const initials = firstNames.split(' ').map(n => n[0] + '.').join(' '); 
        //console.log(`Initials for "${firstNames}": "${initials}"`);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

        const formattedName = `${last}, ${initials}`.trim(); // Rückgabe des formatierten Namens
        //console.log(`Formatted name: "${formattedName}"`);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

        return formattedName;
    });

    //console.log("Formatted authors before adding et al.:", formattedAuthors);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

    // Kombiniere die formatierten Autoren mit korrekter Interpunktion
    const output = formattedAuthors.slice(0, maxAuthors).join('; ') + 
                   (formattedAuthors.length > maxAuthors ? ' et al.' : '');
    
    //console.log("Final output:", output);
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    return output;
};

Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  let specialthing = "";
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  if (special) {
    specialthing = `#${special}`; 
  }
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed

  // Helper function to render individual citations based on their type
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  const renderCitation = (entry: BibEntry, index: number) => {
   // console.log(`Rendering citation for entry #${index + 1}: `, entry);
    
    // Use the index as citation number
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    let citationNumber = index +1; 
    if(start){
      citationNumber += start -1; 
    }
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    const entryType = entry.entryType.toLowerCase(); // Convert to lowercase for consistent comparison
    const entryTags = entry.entryTags; // Adjust based on your data structure
   // console.log("Entry Tags: ", entryTags);

    switch (entryType) {
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      case "article":
        return (
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          <li key={index} typeof="schema:ScholarlyArticle" role="doc-biblioentry" property="schema:citation" id={`desc-${citationNumber}${specialthing}`}>
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
            {/* Citation number as comment */}
            {/*<!-- Citation num ${citationNumber} --> */}
            {formatAuthors(entryTags.AUTHOR || entryTags.EDITOR || "")}
            &nbsp;<span property="schema:name">{entryTags.TITLE.replace(/[?!.]/g, '').replace(/\n/g, ' ').trim()}.</span>
            &nbsp;<i property="schema:publisher" typeof="schema:Organization">{entryTags.JOURNAL}</i>
            &nbsp;<b property="issueNumber" typeof="PublicationIssue">{entryTags.VOLUME}</b>
            {formatPages(entryTags.PAGES) && <span>{formatPages(entryTags.PAGES)}</span>}
            {entryTags.YEAR && (
              <span>&nbsp;(<time property="schema:datePublished" datatype="xsd:gYear" dateTime={entryTags.YEAR}>{entryTags.YEAR}</time>).</span>
            )}
            {entryTags.DOI && (
              <span>&nbsp;<a className="doi" href={`https://doi.org/${entryTags.DOI}`}>doi: {entryTags.DOI}</a></span>
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
            )}
          </li>
        );
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      case "book":
        return (
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          <li key={index} typeof="schema:Book" role="doc-biblioentry" property="schema:citation" id={`desc-${citationNumber}`}>
            {/* Render authors */}
            {formatAuthors(entryTags.AUTHOR || entryTags.EDITOR || "")}
            {/* Render title or booktitle */}
            {entryTags.TITLE ? (
              <span property="schema:name">&nbsp;{entryTags.TITLE.replace(/[?!.]/g, '').replace(/\n/g, ' ').trim()}.</span>
            ) : entryTags.BOOKTITLE ? (
              <span property="schema:name">&nbsp;{entryTags.BOOKTITLE.replace(/[?!.]/g, '').replace(/\n/g, ' ').trim()}.</span>
            ) : (
              console.warn(`No title or booktitle found for entry ${citationNumber}`)
            )}
            {/* Render publisher */}
            {entryTags.PUBLISHER && (
              <i property="schema:publisher" typeof="schema:Organization">
                &nbsp;{entryTags.PUBLISHER}
              </i>
            )}
            {/* Render year */}
            {entryTags.YEAR && (
              <span>
                &nbsp;(<time property="schema:datePublished" datatype="xsd:gYear" dateTime={entryTags.YEAR}>
                  {entryTags.YEAR}
                </time>).
              </span>
            )}
            {entryTags.ISBN && (
              <span property="isbn">&nbsp;{entryTags.ISBN}</span>
            )
            }
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          </li>
        );
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      case "misc":
        return (
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          <li key={index} typeof="schema:WebPage" role="doc-biblioentry" property="schema:citation" id={`desc-${citationNumber}`}>
            {/* Render authors */}
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
            {(entryTags.AUTHOR || entryTags.EDITOR || "")}
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
            {/* Render title */}
            {entryTags.TITLE && (
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
              <span property="schema:name">.&nbsp;{entryTags.TITLE.replace(/[?!.]/g, '').replace(/\n/g, ' ').trim()}.</span>
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
            )}
            {/* Render howpublished */}
            {entryTags.HOWPUBLISHED && (
              <i property="schema:publisher" typeof="schema:Organization">&nbsp;{entryTags.HOWPUBLISHED}</i>
            )}
            {/* Render year */}
            {entryTags.YEAR && (
              <span>&nbsp;(<time property="schema:datePublished" datatype="xsd:gYear" dateTime={entryTags.YEAR}>{entryTags.YEAR}</time>).</span>
            )}
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          </li>
        );
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      // Handle additional entry types here
      case "inproceedings":
        return (
          <li key={index}>
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
            <span>{formatAuthors(entryTags.AUTHOR || "")}</span>&nbsp;
            <span>{entryTags.TITLE}</span>. In <i>{entryTags.BOOKTITLE}</i>,&nbsp;
            <b>{entryTags.editor}</b>, {entryTags.YEAR}.
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          </li>
        );
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      case "phdthesis":
        return (
          <li key={index}>
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
            <span>{formatAuthors(entryTags.AUTHOR || "")}</span>&nbsp;
            <span>{entryTags.TITLE}</span>, PhD thesis, {entryTags.SCHOOL}, {entryTags.YEAR}.
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          </li>
        );
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      default:
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
        console.warn(`Unknown entry type: ${entryType}`);
        return <li key={index}>Unknown entry type: {entryType}</li>;
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    }
  };
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  let startnumber = 1; 
  if(start) {
    startnumber = start; 
  }
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
  return (
    <div>
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
      {parsedEntries.length === 0 ? (
        <p>No citations available.</p>
      ) : (
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
        <ol start={startnumber}>
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
          {parsedEntries.map((entry, index) => renderCitation(entry, index))}
        </ol>
      )}
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
    </div>
  );
};
Liliana Sanfilippo's avatar
Liliana Sanfilippo committed
export default BibtexParser;