From 302baf81d90a2c51316b48a4218245a9c1320e17 Mon Sep 17 00:00:00 2001 From: Alphaharrius Date: Sat, 9 Nov 2024 15:16:48 +0800 Subject: [PATCH] Added citation customization options. --- setup.py | 2 +- src/texmd/bib.py | 49 ++++++++++++++++++++++++++++++++++++++++++ src/texmd/tex.py | 55 +++++++++++++++++++++++++++++------------------- 3 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 src/texmd/bib.py diff --git a/setup.py b/setup.py index ddf67a4..5163d40 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="texmd", - version="0.1.0", + version="0.1.1", description="A simple library that translates LaTeX to Markdown.", package_dir={"": "src"}, packages=find_packages(where="src"), diff --git a/src/texmd/bib.py b/src/texmd/bib.py new file mode 100644 index 0000000..dc20458 --- /dev/null +++ b/src/texmd/bib.py @@ -0,0 +1,49 @@ +from pydantic import BaseModel +from typing import List + + +class Author(BaseModel): + """ An author of a bibliography entry. """ + + first_name: str + """ The first name of the author. """ + + middle_name: str + """ The middle name of the author. """ + + last_name: str + """ The last name of the author. """ + + +class Entry(BaseModel): + """ A bibliography entry. """ + + name: str + """ The name of the entry. """ + + authors: List[Author] + """ The authors of the entry. """ + + title: str + """ The title of the entry. """ + + year: str + """ The year of the entry. """ + + journal: str + """ The journal of the entry. """ + + volume: str + """ The volume of the entry. """ + + number: str + """ The number of the entry. """ + + pages: str + """ The pages of the entry. """ + + doi: str + """ The DOI of the entry. """ + + url: str + """ The URL of the entry. """ diff --git a/src/texmd/tex.py b/src/texmd/tex.py index 5c7fa30..dfb152f 100644 --- a/src/texmd/tex.py +++ b/src/texmd/tex.py @@ -13,7 +13,6 @@ from multipledispatch import dispatch from abc import ABC, abstractmethod from pybtex.database.input import bibtex, BibliographyData -from pybtex.database import Person from texmd.md import ( MdNode, @@ -28,6 +27,8 @@ MdMath, MdEquation) +import texmd.bib as bib + class TexNode(BaseModel, ABC): """ Base class for LaTeX nodes. """ @@ -506,10 +507,20 @@ def __init__(self, parser: 'TexParser'): super().__init__(parser) def convert(self, node: TexMacroNode) -> Generator[MdNode]: + def write_author(author: bib.Author) -> str: + first_abbr = author.first_name[0] + '.' if author.first_name else '' + middle_abbr = author.middle_name[0] + '.' if author.middle_name else '' + return f"{first_abbr} {middle_abbr} {author.last_name}" + + def write_entry(entry: bib.Entry) -> str: + content: List[str] = [*(write_author(author) for author in entry.authors), entry.title, entry.year] + return ", ".join(content) + def _(): chars: TexTextNode = node.children[0].children[0] cite_names = chars.text.replace(' ', '').split(',') citations = (self.parser._get_citation(name) for name in cite_names) + citations = (write_entry(entry) for entry in citations if entry) yield MdText(text="(*" + ", ".join(citations) + "*)") return _() @@ -538,10 +549,10 @@ def __init__(self): (TexGroupNode, 'topic'): TopicGroupConverter(self), (TexGroupNode, 'label:topic'): TopicGroupConverter(self), - (TexEnvNode, 'abstract'): AbstractConverter(self), (TexMacroNode, 'eqref'): RefConverter(self), (TexMacroNode, 'ref'): RefConverter(self), + (TexEnvNode, 'abstract'): AbstractConverter(self), (TexEnvNode, 'equation'): EquationConverter(self), (TexEnvNode, 'align'): EquationConverter(self), (TexEnvNode, 'array'): EquationConverter(self), @@ -706,25 +717,25 @@ def _get_ref_name(self, node: TexEnvNode) -> str: """ Get the label of a LaTeX ref node. """ return self.__ref_names.get(id(node), '') - def _get_citation(self, name: str) -> str: - """ Get the citation of a LaTeX cite node, returns `` if the name is not found. """ + def _get_citation(self, name: str) -> bib.Entry: + """ Get a citation by its name, returns `None` if the citation is not found. """ if not self.__citations or name not in self.__citations.entries: - return '' + return None + entry = self.__citations.entries[name] - citation = [] - authors: List[Person] = entry.persons['author'] - for author in authors: - first_name = " ".join(author.first_names) - middle_name = " ".join(author.middle_names) - last_name = " ".join(author.last_names) - first_abbrev = (first_name[0] + '.' if first_name else '') - middle_abbrev = (middle_name[0] + '.' if middle_name else '') - name = f"{first_abbrev} {middle_abbrev} {last_name}" - citation.append(name) - citation.append(', ') - title = entry.fields['title'] - citation.append(title) - citation.append(', ') - year = entry.fields['year'] if 'year' in entry.fields else '' - citation.append(year) - return "".join(citation) + get_author = lambda v: bib.Author( + first_name=" ".join(v.first_names), + middle_name=" ".join(v.middle_names), + last_name=" ".join(v.last_names)) + authors: List[bib.Author] = [get_author(v) for v in entry.persons['author']] + return bib.Entry( + name=name, + authors=authors, + title=entry.fields['title'] if 'title' in entry.fields else '', + year=entry.fields['year'] if 'year' in entry.fields else '', + journal=entry.fields['journal'] if 'journal' in entry.fields else '', + volume=entry.fields['volume'] if 'volume' in entry.fields else '', + number=entry.fields['number'] if 'number' in entry.fields else '', + pages=entry.fields['pages'] if 'pages' in entry.fields else '', + doi=entry.fields['doi'] if 'doi' in entry.fields else '', + url=entry.fields['url'] if 'url' in entry.fields else '')