v0.6.0 BigUpdate
This commit is contained in:
@@ -52,32 +52,75 @@ class List(Renderable):
|
||||
self._paragraphs.append(paragraph)
|
||||
return paragraph
|
||||
|
||||
@staticmethod
|
||||
def _is_hyphen_run(run) -> bool:
|
||||
"""True for a run that carries only w:noBreakHyphen (text is empty)."""
|
||||
if run.text:
|
||||
return False
|
||||
return bool(run._element.xpath("./w:noBreakHyphen"))
|
||||
|
||||
@classmethod
|
||||
def _logical_text(cls, runs) -> str:
|
||||
parts = []
|
||||
for run in runs:
|
||||
if cls._is_hyphen_run(run):
|
||||
parts.append("-")
|
||||
else:
|
||||
parts.append(run.text or "")
|
||||
return "".join(parts)
|
||||
|
||||
def finalize_punctuation(self) -> None:
|
||||
"""Apply TZ list punctuation: bullet → lowercase + ';' (last '.'); numbered → Capital + '.'."""
|
||||
"""Apply TZ list punctuation: bullet → lowercase + ';' (last '.'); numbered → Capital + '.'.
|
||||
|
||||
Case and the final mark are written into existing runs. Runs are not merged:
|
||||
merging drops w:noBreakHyphen and inline code formatting, so «REST-интерфейс»
|
||||
became «RESTинтерфейс».
|
||||
"""
|
||||
for i, paragraph in enumerate(self._paragraphs):
|
||||
runs = paragraph._docx_paragraph.runs
|
||||
if len(runs) < 2:
|
||||
continue
|
||||
# Text after marker run
|
||||
text_runs = runs[1:]
|
||||
full = "".join(r.text or "" for r in text_runs).strip()
|
||||
logical = self._logical_text(text_runs)
|
||||
full = logical.strip()
|
||||
if not full:
|
||||
continue
|
||||
is_last = i == len(self._paragraphs) - 1
|
||||
if self._ordered:
|
||||
fixed = full[0].upper() + full[1:] if full else full
|
||||
fixed = full[0].upper() + full[1:]
|
||||
if not fixed.endswith("."):
|
||||
fixed = fixed.rstrip(";,. ") + "."
|
||||
else:
|
||||
fixed = full[0].lower() + full[1:] if full else full
|
||||
fixed = full[0].lower() + full[1:]
|
||||
if is_last:
|
||||
fixed = fixed.rstrip(";,. ") + "."
|
||||
else:
|
||||
fixed = fixed.rstrip(";,. ") + ";"
|
||||
# Put all text into first content run, clear others
|
||||
text_runs[0].text = fixed
|
||||
for r in text_runs[1:]:
|
||||
r.text = ""
|
||||
if logical == fixed:
|
||||
continue
|
||||
self._apply_list_punctuation(text_runs, full, fixed)
|
||||
|
||||
@classmethod
|
||||
def _apply_list_punctuation(cls, text_runs, full: str, fixed: str) -> None:
|
||||
if full[0] != fixed[0]:
|
||||
for run in text_runs:
|
||||
if cls._is_hyphen_run(run) or not run.text:
|
||||
continue
|
||||
run.text = fixed[0] + run.text[1:]
|
||||
break
|
||||
desired_end = fixed[-1]
|
||||
last = None
|
||||
for run in text_runs:
|
||||
if cls._is_hyphen_run(run) or not run.text:
|
||||
continue
|
||||
last = run
|
||||
if last is None:
|
||||
return
|
||||
trimmed = last.text.rstrip(";,. ")
|
||||
if trimmed.endswith(desired_end):
|
||||
last.text = trimmed
|
||||
else:
|
||||
last.text = trimmed + desired_end
|
||||
|
||||
def render(self, previous_rendered: RenderedInfo, layout_state: LayoutState) -> Generator[
|
||||
RenderedInfo | Renderable, None, None]:
|
||||
|
||||
Reference in New Issue
Block a user