- add Local Render Mermaid - add page-starе для указания смещения страниц - add Гиперссылки в документе на списки литературы
This commit is contained in:
@@ -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_}?")
|
||||
|
||||
Reference in New Issue
Block a user