v0.5.2
Python application / build (push) Waiting to run

Что то сделал
This commit is contained in:
Igor20264
2026-09-08 19:37:54 +03:00
parent 1a5b35eb54
commit 510f7e7adf
90 changed files with 11720 additions and 5547 deletions
+85
View File
@@ -0,0 +1,85 @@
"""Parse ГОСТ-style captions: Рисунок / Таблица / Листинг (+ продолжения)."""
from __future__ import annotations
import re
from dataclasses import dataclass
from md2gost.word_fix import parse_caption_text
_FIGURE_RE = re.compile(
r"^(?:Рисунок|Рис\.?)\s+(?P<number>[\d.]+)\s*(?:[—–\-]\s*(?P<title>.+))?$",
re.IGNORECASE,
)
_TABLE_FULL_RE = re.compile(
r"^(?:Продолжение\s+)?"
r"(?P<kind>Таблица|Таблицы|Листинг|Листинга)\s+"
r"(?P<number>[\d.]+)"
r"(?:\s*[—–\-]\s*(?P<title>.+))?$",
re.IGNORECASE,
)
_CONTINUATION_RE = re.compile(r"^Продолжение\s+(?:Таблицы|Листинга)\b", re.IGNORECASE)
@dataclass
class ParsedCaption:
kind: str # figure | table | listing
number: str
text: str | None = None
is_continuation: bool = False
def caption_unique_id(kind: str, number: str) -> str:
"""Stable id from display number: 1.1 → fig1_1 / tbl1_1 / lst1_1."""
safe = str(number).replace(".", "_")
prefix = {"figure": "fig", "table": "tbl", "listing": "lst"}.get(kind, "obj")
return f"{prefix}{safe}"
def parse_any_caption(text: str) -> ParsedCaption | None:
"""Parse figure / table / listing captions (including «Продолжение…»)."""
raw = (text or "").replace("\r", "").replace("\x07", "").strip()
if not raw:
return None
first = raw.split("\n", 1)[0].strip()
m = _FIGURE_RE.match(first)
if m:
title = (m.group("title") or "").strip().rstrip(".") or None
return ParsedCaption(kind="figure", number=m.group("number"), text=title)
info = parse_caption_text(first)
if info is not None:
title = None
m2 = _TABLE_FULL_RE.match(first)
if m2 and m2.group("title"):
title = m2.group("title").strip().rstrip(".") or None
else:
# Strip leading «Таблица N — » / «Продолжение…» for leftover title
rest = _TABLE_FULL_RE.sub("", first).strip()
if rest.startswith(("", "", "-")):
rest = rest[1:].strip()
title = rest.rstrip(".") or None if rest else None
return ParsedCaption(
kind=info.kind,
number=info.number,
text=title,
is_continuation=info.is_continuation,
)
m3 = _TABLE_FULL_RE.match(first)
if m3:
kind_raw = m3.group("kind").lower()
if kind_raw.startswith("табл"):
kind = "table"
elif kind_raw.startswith("лист"):
kind = "listing"
else:
return None
return ParsedCaption(
kind=kind,
number=m3.group("number"),
text=(m3.group("title") or "").strip().rstrip(".") or None,
is_continuation=bool(_CONTINUATION_RE.match(first)),
)
return None