"""Bibliography renderable (docx-dependent).""" from __future__ import annotations from copy import copy from typing import Generator from docx.shared import Parented from .bibliography import BiblioEntry from .layout_tracker import LayoutState from .renderable import Renderable from .renderable.paragraph import Paragraph from .rendered_info import RenderedInfo from .sub_renderable import SubRenderable class Bibliography(Renderable): def __init__(self, parent: Parented, entries: list[BiblioEntry], sections: list[tuple[str, list[BiblioEntry]]] | None = None): self._parent = parent self._entries = entries self._sections = sections self._paragraphs: list[Paragraph] = [] if sections: for title, sect_entries in sections: h = Paragraph(parent) try: h.style = "Bibliography Heading" except KeyError: pass h.first_line_indent = 0 h.add_run(title.upper()) self._paragraphs.append(h) for e in sect_entries: self._paragraphs.append(self._make_entry(parent, e)) else: for e in entries: self._paragraphs.append(self._make_entry(parent, e)) @staticmethod def _make_entry(parent: Parented, e: BiblioEntry) -> Paragraph: from .bibliography import biblio_bookmark_name p = Paragraph(parent) try: p.style = "Bibliography" except KeyError: pass # Avoid hyphen-splitting URLs: put whole entry in one run via direct text p._docx_paragraph.add_run(f"{e.key}. {e.text}") p.wrap_with_bookmark(biblio_bookmark_name(e.key)) return p def render(self, previous_rendered: RenderedInfo, layout_state: LayoutState) -> Generator[ RenderedInfo | SubRenderable, None, None]: for paragraph in self._paragraphs: for x in paragraph.render(previous_rendered, copy(layout_state)): layout_state.add_height(x.height) previous_rendered = x yield x