unknown
Claude Opus 5.5
Journal Formatter: footnotes, web references, books and reports, author marks, cleaner LaTeX
2eb3609
Raw History Blame Contribute Delete
3.86 kB
"""Intermediate document model shared by all readers and writers."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, List, Optional
# Block roles
TITLE = "title"
AUTHOR = "author"
AFFIL = "affiliation"
ABSTRACT = "abstract"
KEYWORDS = "keywords"
HEADING = "heading"
PARA = "para"
LIST = "list"
TABLE = "table"
FIGURE = "figure"
CAPTION = "caption"
EQUATION = "equation"
REFERENCE = "reference"
OTHER_FRONT = "front" # correspondence, dates, etc.
ABSTRACT_HEADING = "abstract_heading" # standalone "Abstract" label line
ALGORITHM = "algorithm"
FN_MARK = "\u2063" # invisible separator: a footnote's place in the text (never matched by citation rules)
@dataclass
class Run:
text: str = ""
bold: bool = False
italic: bool = False
sup: bool = False
sub: bool = False
# inline equation: OMML XML string (docx source) and/or LaTeX
omml: Optional[str] = None
latex: Optional[str] = None
# citation marker produced by the citation engine
cite: bool = False
# verbatim source run (e.g. MathType / Equation Editor OLE object) + its preview image (blob, ext)
raw: Any = None
img: Any = None
# footnote: this run is the footnote's mark in the text (text = FN_MARK) and `note` is the footnote itself
note: Optional[str] = None
@property
def is_math(self) -> bool:
return self.omml is not None or self.latex is not None or self.raw is not None or \
(self.img is not None and not self.text)
@dataclass
class Block:
role: str
runs: List[Run] = field(default_factory=list)
level: int = 0 # heading level (1..4)
ordered: bool = False # list
list_level: int = 0
rows: Optional[List[List[str]]] = None # table cells (plain text)
image: Optional[bytes] = None # figure
image_ext: str = "png"
width_in: Optional[float] = None
height_in: Optional[float] = None
cap_kind: str = "" # caption: 'figure' | 'table'
cap_num: Optional[int] = None
label: str = "" # e.g. abstract sub-heading "Purpose"
style_name: str = "" # original style (diagnostics)
eq_num: Optional[str] = None # equation number text
orig: str = "" # original paragraph text (before cleaning)
src: Any = None # source XML element (docx) – used by template analysis
src_size: float = 0.0
src_font: str = ""
src_bold: bool = False
prefix: str = "" # generated numbering/label text (heading no., caption label)
raw: Optional[list] = None # verbatim source XML elements (equations, algorithms, complex tables)
lines: Optional[list] = None # algorithm lines: [(indent_level, [Run])]
rows_runs: Optional[list] = None # table cells as runs (keeps inline maths/formatting)
tex_src: str = "" # original LaTeX source (algorithms from .tex input)
@property
def text(self) -> str:
return "".join(r.text if not r.is_math else (r.latex or "[math]") for r in self.runs)
def set_text(self, text: str):
self.runs = [Run(text)]
@dataclass
class Document:
blocks: List[Block] = field(default_factory=list)
source_type: str = ""
warnings: List[str] = field(default_factory=list)
src_docx: Any = None # python-docx Document the blocks were read from (for raw XML parts)
tex_preamble: List[str] = field(default_factory=list) # \\usepackage lines needed by verbatim LaTeX blocks
def by_role(self, role):
return [b for b in self.blocks if b.role == role]
def first(self, role):
for b in self.blocks:
if b.role == role:
return b
return None