156 lines
5.7 KiB
Python
156 lines
5.7 KiB
Python
import os
|
|
|
|
import docx
|
|
from docx.document import Document
|
|
|
|
from .debugger import Debugger
|
|
from .parser_ import Parser
|
|
from .toc_processor import TocProcessor
|
|
from .renderer import Renderer
|
|
from .styles import apply_document_styles
|
|
from .profiles import (
|
|
preprocess_markdown,
|
|
find_formula_refs,
|
|
get_profile,
|
|
DEFAULT_HEADING_NUMBERING,
|
|
HEADING_NUMBERING_MODES,
|
|
DEFAULT_TOC_MODE,
|
|
TOC_MODES,
|
|
DEFAULT_TABLE_CONTINUATION,
|
|
DEFAULT_LISTING_CONTINUATION,
|
|
TABLE_CONTINUATION_MODES,
|
|
LISTING_CONTINUATION_MODES,
|
|
)
|
|
from .label_pass import (
|
|
assign_numbers,
|
|
set_active_registry,
|
|
resolve_reference,
|
|
resolve_pending_in_renderables,
|
|
)
|
|
from .renderable.heading import Heading
|
|
from .renderable.toc import ToC
|
|
from .renderable.table import Table
|
|
from .renderable.listing import Listing
|
|
from .renderable.diagram import DiagramFigure
|
|
|
|
|
|
class Converter:
|
|
"""Converts markdown file to docx file (MIREA TZ)."""
|
|
|
|
def __init__(self, input_path: str, output_path: str,
|
|
template_path: str = None, debug: bool = False,
|
|
doc_type: str = "practice",
|
|
heading_numbering: str = DEFAULT_HEADING_NUMBERING,
|
|
emdash_to_hyphen: bool = False,
|
|
toc_mode: str = DEFAULT_TOC_MODE,
|
|
table_continuation: str = DEFAULT_TABLE_CONTINUATION,
|
|
listing_continuation: str = DEFAULT_LISTING_CONTINUATION,
|
|
hr_pagebreak: bool = False,
|
|
styles_path: str | None = None,
|
|
markdown_text: str | None = None):
|
|
if heading_numbering not in HEADING_NUMBERING_MODES:
|
|
raise ValueError(
|
|
f"heading_numbering must be one of {HEADING_NUMBERING_MODES}, "
|
|
f"got {heading_numbering!r}"
|
|
)
|
|
if toc_mode not in TOC_MODES:
|
|
raise ValueError(
|
|
f"toc_mode must be one of {TOC_MODES}, got {toc_mode!r}"
|
|
)
|
|
if table_continuation not in TABLE_CONTINUATION_MODES:
|
|
raise ValueError(
|
|
f"table_continuation must be one of {TABLE_CONTINUATION_MODES}, "
|
|
f"got {table_continuation!r}"
|
|
)
|
|
if listing_continuation not in LISTING_CONTINUATION_MODES:
|
|
raise ValueError(
|
|
f"listing_continuation must be one of {LISTING_CONTINUATION_MODES}, "
|
|
f"got {listing_continuation!r}"
|
|
)
|
|
self._output_path = output_path
|
|
self._doc_type = doc_type
|
|
self._heading_numbering = heading_numbering
|
|
self._emdash_to_hyphen = emdash_to_hyphen
|
|
self._toc_mode = toc_mode
|
|
self._table_continuation = table_continuation
|
|
self._listing_continuation = listing_continuation
|
|
self._hr_pagebreak = hr_pagebreak
|
|
self._styles_path = styles_path
|
|
self._profile = get_profile(doc_type)
|
|
self._document: Document = docx.Document(template_path)
|
|
self._document._body.clear_content()
|
|
md_dir = os.path.dirname(os.path.abspath(input_path)) or "."
|
|
os.environ["WORKING_DIR"] = md_dir
|
|
self._style_config = apply_document_styles(
|
|
self._document,
|
|
self._profile.style_preset,
|
|
md_dir=md_dir,
|
|
styles_path=styles_path,
|
|
)
|
|
self._debugger = Debugger(self._document) if debug else None
|
|
if markdown_text is not None:
|
|
raw = markdown_text
|
|
else:
|
|
with open(input_path, encoding="utf-8") as f:
|
|
raw = f.read()
|
|
self._raw_markdown = raw
|
|
self._preprocessed = preprocess_markdown(raw, emdash_to_hyphen=emdash_to_hyphen)
|
|
self.parser = Parser(self._document, self._preprocessed, hr_pagebreak=hr_pagebreak)
|
|
|
|
def convert(self):
|
|
renderables = list(self.parser.parse())
|
|
from .biblio_processor import fold_bibliography
|
|
renderables = fold_bibliography(
|
|
renderables, self._document._body, raw_markdown=self._preprocessed
|
|
)
|
|
|
|
# Resolve heading numbering mode + TOC mode + table continuation
|
|
for r in renderables:
|
|
if isinstance(r, Heading):
|
|
r.apply_numbering_mode(self._heading_numbering)
|
|
elif isinstance(r, ToC):
|
|
r.set_heading_numbering(self._heading_numbering)
|
|
r.set_toc_mode(self._toc_mode)
|
|
elif isinstance(r, Table):
|
|
r.set_continuation_mode(self._table_continuation)
|
|
elif isinstance(r, Listing):
|
|
r.set_continuation_mode(self._listing_continuation)
|
|
elif isinstance(r, DiagramFigure) and r.listing:
|
|
r.listing.set_continuation_mode(self._listing_continuation)
|
|
|
|
formula_refs = find_formula_refs(self._raw_markdown)
|
|
registry = assign_numbers(
|
|
renderables, formula_refs,
|
|
numbering_scope=self._profile.numbering_scope,
|
|
)
|
|
set_active_registry(registry)
|
|
resolve_pending_in_renderables(renderables, resolve_reference)
|
|
|
|
renderer = Renderer(self._document, self._debugger,
|
|
numbered_equations=formula_refs,
|
|
skip_numbering=True,
|
|
numbering_scope=self._profile.numbering_scope)
|
|
renderer.process(renderables)
|
|
TocProcessor().process(renderables)
|
|
set_active_registry(None)
|
|
|
|
@property
|
|
def document(self) -> Document:
|
|
return self._document
|
|
|
|
@property
|
|
def style_config(self):
|
|
return self._style_config
|
|
|
|
@property
|
|
def raw_markdown(self) -> str:
|
|
return self._raw_markdown
|
|
|
|
@property
|
|
def doc_type(self) -> str:
|
|
return self._doc_type
|
|
|
|
@property
|
|
def heading_numbering(self) -> str:
|
|
return self._heading_numbering
|