An MkDocs plugin that enables managing citations with BibTex
—
Registry system for managing bibliographic data, citation formatting, and reference text generation. The module provides an abstract base class and two concrete implementations for different formatting approaches.
Abstract base class that defines the interface for bibliography management systems.
from abc import ABC, abstractmethod
from typing import Union
class ReferenceRegistry(ABC):
"""
A registry of references that can be used to format citations
"""
def __init__(self, bib_files: list[str], footnote_format: str = "{key}"):
"""
Initialize the registry with bibliography files.
Args:
bib_files (list[str]): List of paths to BibTeX files
footnote_format (str): Template for footnote formatting, must contain {key}
"""
@abstractmethod
def validate_citation_blocks(self, citation_blocks: list[CitationBlock]) -> None:
"""
Validates all citation blocks. Throws an error if any citation block is invalid.
Args:
citation_blocks (list[CitationBlock]): Citation blocks to validate
"""
@abstractmethod
def validate_inline_references(self, inline_references: list[InlineReference]) -> set[InlineReference]:
"""
Validates inline references and returns only the valid ones.
Args:
inline_references (list[InlineReference]): Inline references to validate
Returns:
set[InlineReference]: Set of valid inline references
"""
@abstractmethod
def inline_text(self, citation_block: CitationBlock) -> str:
"""
Retrieves the inline citation text for a citation block.
Args:
citation_block (CitationBlock): Citation block to format
Returns:
str: Formatted inline citation text
"""
@abstractmethod
def reference_text(self, citation: Union[Citation, InlineReference]) -> str:
"""
Retrieves the reference text for a citation or inline reference.
Args:
citation (Union[Citation, InlineReference]): Citation to format
Returns:
str: Formatted reference text for bibliography
"""Simple reference registry using pybtex for basic formatting without CSL support.
class SimpleRegistry(ReferenceRegistry):
"""Simple registry using pybtex formatting"""
def __init__(self, bib_files: list[str], footnote_format: str = "{key}"):
"""
Initialize simple registry with pybtex backend.
Args:
bib_files (list[str]): List of paths to BibTeX files
footnote_format (str): Template for footnote formatting
"""
def validate_citation_blocks(self, citation_blocks: list[CitationBlock]) -> None:
"""
Validates all citation blocks, logging warnings for unknown keys and unsupported features.
- Warns about unknown citation keys
- Warns about prefix/suffix usage (not supported in simple mode)
Args:
citation_blocks (list[CitationBlock]): Citation blocks to validate
"""
def validate_inline_references(self, inline_references: list[InlineReference]) -> set[InlineReference]:
"""
Validates inline references, returning only those with valid keys.
Args:
inline_references (list[InlineReference]): Inline references to validate
Returns:
set[InlineReference]: Valid inline references
"""
def inline_text(self, citation_block: CitationBlock) -> str:
"""
Generates inline citation text as footnote links.
Args:
citation_block (CitationBlock): Citation block to format
Returns:
str: Footnote links like "[^key1][^key2]"
"""
def reference_text(self, citation: Union[Citation, InlineReference]) -> str:
"""
Generates reference text using pybtex plain style.
Args:
citation (Union[Citation, InlineReference]): Citation to format
Returns:
str: Formatted bibliography entry
"""Advanced reference registry using Pandoc with CSL support for professional citation formatting.
class PandocRegistry(ReferenceRegistry):
"""A registry that uses Pandoc to format citations"""
def __init__(self,
bib_files: list[str],
csl_file: str,
csl_file_encoding: Union[str, None],
footnote_format: str = "{key}"):
"""
Initialize Pandoc registry with CSL support.
Args:
bib_files (list[str]): List of paths to BibTeX files
csl_file (str): Path to CSL style file
csl_file_encoding (Union[str, None]): CSL file encoding
footnote_format (str): Template for footnote formatting
Raises:
ValueError: If Pandoc version is less than 2.11
"""
def validate_citation_blocks(self, citation_blocks: list[CitationBlock]) -> None:
"""
Validates citation blocks and pre-formats all citations using Pandoc.
Process:
1. Validate all citation keys exist in bibliography
2. Process unformatted citations through Pandoc
3. Cache formatted results for performance
Args:
citation_blocks (list[CitationBlock]): Citation blocks to validate and format
"""
def validate_inline_references(self, inline_references: list[InlineReference]) -> set[InlineReference]:
"""
Validates inline references and processes them through Pandoc.
Args:
inline_references (list[InlineReference]): Inline references to validate
Returns:
set[InlineReference]: Valid inline references
"""
def inline_text(self, citation_block: CitationBlock) -> str:
"""
Get the inline text for a citation block from Pandoc processing.
For inline CSL styles: returns both inline citation and footnote links
For footnote CSL styles: returns only footnote links
Args:
citation_block (CitationBlock): Citation block to format
Returns:
str: Formatted inline citation text
"""
def reference_text(self, citation: Union[Citation, InlineReference]) -> str:
"""
Returns cached reference text from Pandoc processing.
Args:
citation (Union[Citation, InlineReference]): Citation to get reference for
Returns:
str: Formatted bibliography entry
"""
@cached_property
def bib_data_bibtex(self) -> str:
"""
Convert bibliography data to BibTeX format string.
Returns:
str: Bibliography data in BibTeX format
"""Both registry implementations maintain bibliography data and formatting state.
# Common attributes
bib_data: BibliographyData # Parsed bibliography data from pybtex
footnote_format: str # Template for footnote formatting
# SimpleRegistry specific
style: PlainStyle # pybtex plain formatting style
backend: MarkdownBackend # pybtex markdown backend
# PandocRegistry specific
csl_file: str # Path to CSL style file
_inline_cache: dict[str, str] # Cache for formatted inline citations
_reference_cache: dict[str, str] # Cache for formatted reference text
_is_inline: bool # Whether CSL style uses inline formatfrom mkdocs_bibtex.registry import SimpleRegistry
from mkdocs_bibtex.citation import CitationBlock
# Initialize simple registry
registry = SimpleRegistry(
bib_files=["refs.bib"],
footnote_format="{key}"
)
# Process citations
citation_blocks = CitationBlock.from_markdown("[@smith2020]")
registry.validate_citation_blocks(citation_blocks)
# Generate inline text
inline_text = registry.inline_text(citation_blocks[0])
print(inline_text) # "[^smith2020]"
# Generate reference text
ref_text = registry.reference_text(citation_blocks[0].citations[0])
print(ref_text) # "Smith, J. Title. Journal, 2020."from mkdocs_bibtex.registry import PandocRegistry
from mkdocs_bibtex.citation import CitationBlock
# Initialize Pandoc registry with CSL
registry = PandocRegistry(
bib_files=["refs.bib"],
csl_file="apa.csl",
csl_file_encoding=None,
footnote_format="{key}"
)
# Process citations (includes Pandoc formatting)
citation_blocks = CitationBlock.from_markdown("[@smith2020, pp. 100-120]")
registry.validate_citation_blocks(citation_blocks)
# Generate formatted inline text
inline_text = registry.inline_text(citation_blocks[0])
print(inline_text) # "(Smith, 2020, pp. 100-120)[^smith2020]"
# Generate formatted reference text
ref_text = registry.reference_text(citation_blocks[0].citations[0])
print(ref_text) # "Smith, J. (2020). Title. Journal, 15(3), 123-145."from mkdocs_bibtex.registry import SimpleRegistry, PandocRegistry
def create_registry(bib_files, csl_file=None, footnote_format="{key}"):
"""Create appropriate registry based on CSL availability."""
if csl_file:
return PandocRegistry(
bib_files=bib_files,
csl_file=csl_file,
csl_file_encoding=None,
footnote_format=footnote_format
)
else:
return SimpleRegistry(
bib_files=bib_files,
footnote_format=footnote_format
)
# Usage in plugin
registry = create_registry(
bib_files=["refs.bib"],
csl_file="chicago.csl" if use_csl else None
)The PandocRegistry automatically detects CSL style types:
CSL files with citation-format="author-date" produce inline citations:
According to (Smith, 2020), the method works.CSL files with numeric or other formats produce footnote-only citations:
According to Smith¹, the method works.The PandocRegistry implements sophisticated caching:
# Citation validation
try:
registry.validate_citation_blocks(citation_blocks)
except Exception as e:
logger.error(f"Citation validation failed: {e}")
# Reference existence check
valid_refs = registry.validate_inline_references(inline_refs)
invalid_count = len(inline_refs) - len(valid_refs)
if invalid_count > 0:
logger.warning(f"Found {invalid_count} invalid inline references")Install with Tessl CLI
npx tessl i tessl/pypi-mkdocs-bibtex