BigUpdate 0.5.0
Python application / build (push) Has been cancelled

- add Local Render Mermaid
- add page-starе для указания смещения страниц
- add Гиперссылки в документе на списки литературы
This commit is contained in:
Igor20264
2026-09-07 09:54:33 +03:00
parent ac0aa33399
commit 1a5b35eb54
29 changed files with 4118 additions and 69 deletions
+109 -2
View File
@@ -1,10 +1,9 @@
from copy import copy
from typing import Generator, Any
from typing import Generator
from docx.shared import Length, Parented, RGBColor
from docx.text.paragraph import Paragraph as DocxParagraph
from docx.text.paragraph import Run as DocxRun
from docx.enum.text import WD_LINE_SPACING
from docx.opc.constants import RELATIONSHIP_TYPE
from . import Renderable
@@ -17,6 +16,14 @@ from ..util import create_element
from ..rendered_info import RenderedInfo
from ..latex_math import latex_to_omml, inline_omml
_bookmark_seq = 0
def _next_bookmark_id() -> int:
global _bookmark_seq
_bookmark_seq += 1
return _bookmark_seq
class Link:
def __init__(self, url, docx_paragraph: DocxParagraph):
@@ -48,6 +55,39 @@ class Link:
return self._hyperlink
class InternalLink:
"""Hyperlink to a bookmark in the same document (w:anchor)."""
def __init__(self, anchor: str, docx_paragraph: DocxParagraph):
self._docx_paragraph = docx_paragraph
self._hyperlink = create_element("w:hyperlink", {"w:anchor": anchor})
def add_run(
self,
text: str,
is_bold: bool = None,
is_italic: bool = None,
color: RGBColor = None,
strike_through: bool = None,
):
docx_run = DocxRun(create_element("w:r"), self._docx_paragraph)
self._hyperlink.append(docx_run._element)
docx_run.text = text
try:
docx_run.style = "Hyperlink"
except KeyError:
pass
docx_run.bold = is_bold
docx_run.italic = is_italic
if color is not None:
docx_run.font.color.rgb = color
docx_run.font.strike = strike_through
@property
def element(self):
return self._hyperlink
class Paragraph(Renderable):
def __init__(self, parent: Parented):
self._parent = parent
@@ -70,6 +110,73 @@ class Paragraph(Renderable):
self._docx_paragraph.add_run()._element.\
append(create_element("w:noBreakHyphen"))
def add_run_with_citations(
self,
text: str,
is_bold: bool = None,
is_italic: bool = None,
color: RGBColor = None,
strike_through: bool = None,
):
"""Split body text so [1] / [2, 3] become internal links to bibliography bookmarks."""
import re
from ..bibliography import CITE_RE
kw = dict(
is_bold=is_bold, is_italic=is_italic, color=color, strike_through=strike_through,
)
pos = 0
for m in CITE_RE.finditer(text):
if m.start() > pos:
self.add_run(text[pos:m.start()], **kw)
full = m.group(0)
inner = m.group(1)
self.add_run("[", **kw)
for token in re.split(r"(\s*,\s*)", inner):
if re.fullmatch(r"\d+(?:\.\d+)?", (token or "").strip()):
self.add_biblio_link(token.strip(), token, **kw)
elif token:
self.add_run(token, **kw)
suffix = full[1 + len(inner):-1]
if suffix:
self.add_run(suffix, **kw)
self.add_run("]", **kw)
pos = m.end()
if pos < len(text):
self.add_run(text[pos:], **kw)
def add_biblio_link(
self,
key: str,
text: str | None = None,
is_bold: bool = None,
is_italic: bool = None,
color: RGBColor = None,
strike_through: bool = None,
):
from ..bibliography import biblio_bookmark_name
link = InternalLink(biblio_bookmark_name(key), self._docx_paragraph)
link.add_run(
text if text is not None else key,
is_bold=is_bold,
is_italic=is_italic,
color=color,
strike_through=strike_through,
)
self._docx_paragraph._p.append(link.element)
return link
def wrap_with_bookmark(self, name: str) -> None:
"""Surround current paragraph content with a Word bookmark."""
bid = str(_next_bookmark_id())
p = self._docx_paragraph._p
start = create_element("w:bookmarkStart", {"w:id": bid, "w:name": name})
end = create_element("w:bookmarkEnd", {"w:id": bid})
p.insert(0, start)
p.append(end)
def add_reference(self, type_: str, name: str):
"""Placeholder run resolved later via resolve_pending_refs()."""
run = self._docx_paragraph.add_run(f"{type_}?")