An MkDocs plugin that enables managing citations with BibTex
—
File handling, URL processing, and path resolution utilities that support remote BibTeX file downloading, Zotero API integration, and MkDocs path resolution.
Functions for downloading bibliography and CSL files from remote URLs with robust error handling and caching.
def tempfile_from_url(name: str, url: str, suffix: str) -> str:
"""
Download bibfile from a URL to a temporary file.
Features:
- Automatic retry (up to 3 attempts)
- Special handling for Zotero API URLs
- UTF-8 encoding for downloaded content
- Temporary file with specified suffix
Args:
name (str): Descriptive name for logging purposes
url (str): URL to download from
suffix (str): File suffix for temporary file (e.g., ".bib")
Returns:
str: Path to downloaded temporary file
Raises:
RuntimeError: If download fails after retries or HTTP status != 200
Note:
Temporary files are not automatically deleted
"""
def tempfile_from_zotero_url(name: str, url: str, suffix: str) -> str:
"""
Download bibfile from the Zotero API with pagination support.
Features:
- Automatic pagination following "next" links
- Query parameter sanitization for BibTeX format
- Maximum 999 pages (supports ~100k items)
- Retry logic for network errors
Args:
name (str): Descriptive name for logging purposes
url (str): Zotero API URL
suffix (str): File suffix for temporary file
Returns:
str: Path to downloaded temporary file containing all pages
Raises:
RuntimeError: If download fails or HTTP status != 200
"""Functions for processing and sanitizing URLs, particularly for Zotero API integration.
def sanitize_zotero_query(url: str) -> str:
"""
Sanitize query params in the Zotero URL.
The query params are amended to meet the following requirements:
- mkdocs-bibtex expects all bib data to be in bibtex format.
- Requesting the maximum number of items (100) reduces the requests
required, hence reducing load times.
Args:
url (str): Original Zotero API URL
Returns:
str: Sanitized URL with format=bibtex and limit=100 parameters
Note:
Preserves existing query parameters while overriding format and limit
"""Functions for resolving file paths relative to MkDocs configuration.
def get_path_relative_to_mkdocs_yaml(path: str, config: MkDocsConfig) -> str:
"""
Get the relative path of a file to the mkdocs.yaml file.
Args:
path (str): File path (relative or absolute)
config (MkDocsConfig): MkDocs configuration object
Returns:
str: Normalized absolute path relative to mkdocs.yml location
Note:
Uses os.path.normpath for cross-platform compatibility
"""Module-level logging configuration for the plugin.
import logging
log: logging.Logger
"""
Logger instance for the mkdocs-bibtex plugin.
Logger name: "mkdocs.plugins.mkdocs-bibtex"
Used throughout the plugin for consistent logging.
"""from mkdocs_bibtex.utils import tempfile_from_url
# Download BibTeX file from URL
url = "https://example.com/references.bib"
temp_file = tempfile_from_url("bibliography", url, ".bib")
print(f"Downloaded to: {temp_file}")
# Downloaded to: /tmp/tmpXXXXXX.bib
# File can now be used with pybtex
from pybtex.database import parse_file
bib_data = parse_file(temp_file)from mkdocs_bibtex.utils import tempfile_from_zotero_url
# Download from Zotero group library
zotero_url = "https://api.zotero.org/groups/12345/items?format=bibtex"
temp_file = tempfile_from_zotero_url("Zotero library", zotero_url, ".bib")
print(f"Downloaded {temp_file}")
# Automatically handles pagination and downloads all itemsfrom mkdocs_bibtex.utils import sanitize_zotero_query
# Original URL with custom parameters
original_url = "https://api.zotero.org/groups/12345/items?tag=research"
# Sanitize for mkdocs-bibtex requirements
sanitized_url = sanitize_zotero_query(original_url)
print(sanitized_url)
# https://api.zotero.org/groups/12345/items?tag=research&format=bibtex&limit=100from mkdocs_bibtex.utils import get_path_relative_to_mkdocs_yaml
# Resolve relative path
relative_path = "bibliography/refs.bib"
absolute_path = get_path_relative_to_mkdocs_yaml(relative_path, mkdocs_config)
print(f"Resolved path: {absolute_path}")
# /project/docs/bibliography/refs.bib (example)from mkdocs_bibtex.utils import tempfile_from_url, get_path_relative_to_mkdocs_yaml
import validators
def load_bibliography_file(bib_file_config, mkdocs_config):
"""Load bibliography file from local path or URL."""
if validators.url(bib_file_config):
# Remote file - download to temporary location
return tempfile_from_url("bib file", bib_file_config, ".bib")
else:
# Local file - resolve relative to mkdocs.yml
return get_path_relative_to_mkdocs_yaml(bib_file_config, mkdocs_config)
# Usage in plugin
bib_file_path = load_bibliography_file(config.bib_file, mkdocs_config)The download functions implement robust error handling:
def download_with_retries(url, max_retries=3):
"""Example of retry logic used in the utility functions."""
for attempt in range(max_retries):
try:
response = requests.get(url)
if response.status_code == 200:
return response.text
else:
raise RuntimeError(f"HTTP {response.status_code}")
except requests.exceptions.RequestException:
if attempt == max_retries - 1:
raise RuntimeError(f"Failed to download after {max_retries} attempts")
continueimport os
from pathlib import Path
def safe_path_resolution(path, config):
"""Safe path resolution with error handling."""
try:
resolved_path = get_path_relative_to_mkdocs_yaml(path, config)
if not os.path.exists(resolved_path):
raise FileNotFoundError(f"File not found: {resolved_path}")
return resolved_path
except Exception as e:
logger.error(f"Path resolution failed for {path}: {e}")
raiseThe Zotero integration handles API pagination automatically:
The sanitize_zotero_query function ensures proper API parameters:
All utility functions use consistent logging:
from mkdocs_bibtex.utils import log
# Usage patterns in utility functions
log.debug(f"Downloading {name} from URL {url}")
log.info(f"{name} downloaded to temporary file")
log.warning(f"Exceeded maximum pages. Found: {page_num} pages")
log.error(f"Failed to download: {url}")This provides comprehensive debugging information when MkDocs is run with verbose flags (mkdocs build -v).
Install with Tessl CLI
npx tessl i tessl/pypi-mkdocs-bibtex