diff --git a/book.toml b/book.toml index 206b2b5041..552209beb3 100644 --- a/book.toml +++ b/book.toml @@ -53,10 +53,11 @@ wikidata-template = "https://www.wikidata.org/entity/{wikidata_id}" [preprocessor.citations] command = "python3 ./scripts/preprocessor_citations.py" -bibtex_file = "references.bib" -citation_style = "alpha" -citation_label_style = "custom_alpha" -error_on_unmatched_keys = true +bibtex-file = "references.bib" +citation-style = "alpha" +citation-label-style = "custom_alpha" +error-on-unmatched-keys = true +error-on-empty-bibliography = true before = [ "git-metadata" ] [output.linkcheck] diff --git a/references.bib b/references.bib index 4c31aee2eb..dbb074617f 100644 --- a/references.bib +++ b/references.bib @@ -117,7 +117,8 @@ @unpublished{Cisinski24 date = {2024-08-10}, year = {2024}, month = {08}, - note = {\url{https://drive.google.com/file/d/1lKaq7watGGl3xvjqw9qHjm6SDPFJ2-0o/view}}, + url = {https://drive.google.com/file/d/1lKaq7watGGl3xvjqw9qHjm6SDPFJ2-0o/view}, + note = {}, annote = {} } @@ -328,8 +329,7 @@ @incollection{Makkai98 mrclass = {03B15 (00A30 03A05 03G30 18A15 18D05)}, mrnumber = {1678360}, mrreviewer = {Peter\ Johnstone}, - doi = {10.1007/978-3-662-22108-2\_11}, - url = {https://doi.org/10.1007/978-3-662-22108-2_11} + doi = {10.1007/978-3-662-22108-2\_11} } @book{May12, diff --git a/scripts/preprocessor_citations.py b/scripts/preprocessor_citations.py index ea5a81b9ba..4b40cc1de5 100644 --- a/scripts/preprocessor_citations.py +++ b/scripts/preprocessor_citations.py @@ -23,6 +23,7 @@ DEFAULT_CITATION_STYLE = 'alpha' DEFAULT_LABEL_CITATION_STYLE = 'custom_alpha' DEFAULT_ERROR_ON_UNMATCHED_CITE_KEY = True +DEFAULT_ERROR_ON_EMPTY_BIBLIOGRAPHY = True # Regex to match citation macros CITE_REGEX = re.compile(r'\{\{#cite\s([^\}\s]+)(?:\s(.*))?\}\}') @@ -125,7 +126,8 @@ def process_citations_chapter_rec_mut( bib_database: pybtex.database.BibliographyData, style: pybtex.style.formatting.BaseStyle, backend, - unmatched_cite_keys: set): + unmatched_cite_keys: set, + empty_bibliography_invocations: set): cited_keys = set() # Set to keep track of all cited keys content = chapter.get('content', '') new_content = CITE_REGEX.sub(lambda match: format_citation( @@ -150,10 +152,14 @@ def sub_reference_regex_lambda(m): new_content = insert_bibliography_at_correct_location( new_content, bibliography_section) + elif BIBLIOGRAPHY_REGEX.search(new_content): + eprint(f"Error! A #bibliography macro was found, but there are no references. File: '{chapter['path']}'.") + empty_bibliography_invocations.add(chapter['path']) + chapter['content'] = new_content process_citations_sections_rec_mut( - chapter['sub_items'], bib_database, style, backend, unmatched_cite_keys) + chapter['sub_items'], bib_database, style, backend, unmatched_cite_keys, empty_bibliography_invocations) def insert_bibliography_at_correct_location(content, bibliography_section): @@ -177,14 +183,15 @@ def process_citations_sections_rec_mut( bib_database, style: pybtex.style.formatting.BaseStyle, backend: pybtex.backends.BaseBackend, - unmatched_cite_keys: set): + unmatched_cite_keys: set, + empty_bibliography_invocations: set): for section in sections: chapter = section.get('Chapter') if chapter is None: continue process_citations_chapter_rec_mut( - chapter, bib_database, style, backend, unmatched_cite_keys) + chapter, bib_database, style, backend, unmatched_cite_keys, empty_bibliography_invocations) def process_citations_root_section( @@ -192,11 +199,12 @@ def process_citations_root_section( bib_database: pybtex.database.BibliographyData, style: pybtex.style.formatting.BaseStyle, backend: pybtex.backends.BaseBackend, - unmatched_cite_keys: set): + unmatched_cite_keys: set, + empty_bibliography_invocations: set): chapter = section.get('Chapter') if chapter is not None: process_citations_chapter_rec_mut( - chapter, bib_database, style, backend, unmatched_cite_keys) + chapter, bib_database, style, backend, unmatched_cite_keys, empty_bibliography_invocations) return section @@ -219,16 +227,17 @@ def does_support_backend(backend): citations_config = context['config']['preprocessor']['citations'] unmatched_cite_keys = set() + empty_bibliography_invocations = set() if bool(citations_config.get('enable', True)): bib_database: pybtex.database.BibliographyData = pybtex.database.parse_file( - citations_config.get('bibtex_file')) + citations_config.get('bibtex-file')) # Config citation_style_config = citations_config.get( - 'citation_style', DEFAULT_CITATION_STYLE) + 'citation-style', DEFAULT_CITATION_STYLE) label_style_config = citations_config.get( - 'citation_label_style', DEFAULT_LABEL_CITATION_STYLE) + 'citation-label-style', DEFAULT_LABEL_CITATION_STYLE) backend_config = 'custom_html' # Initialize pybtex classes @@ -250,7 +259,7 @@ def does_support_backend(backend): book['sections'] = list(map( lambda s: process_citations_root_section( - s, bib_database, style, backend, unmatched_cite_keys), + s, bib_database, style, backend, unmatched_cite_keys, empty_bibliography_invocations), book['sections'])) else: eprint('Skipping citation insertion, enable option was set to', @@ -261,5 +270,11 @@ def does_support_backend(backend): if unmatched_cite_keys: eprint("The following unmatched bibliography keys were found while processing citations: ", ", ".join(sorted(unmatched_cite_keys))) - if citations_config.get('error_on_unmatched_keys', DEFAULT_ERROR_ON_UNMATCHED_CITE_KEY): + if citations_config.get('error-on-unmatched-keys', DEFAULT_ERROR_ON_UNMATCHED_CITE_KEY): sys.exit(1) + + if empty_bibliography_invocations: + eprint("The following files have #bibliography macro invocations with empty bibliographies: ", ", ".join(sorted(empty_bibliography_invocations))) + + if citations_config.get('error-on-empty-bibliography', DEFAULT_ERROR_ON_EMPTY_BIBLIOGRAPHY): + sys.exit(2)