From 1a2c03f9999c6783fca89edd23e07609e9375a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8C=D1=8F=20=D0=9F=D0=BE=D0=BB=D1=8F=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Mon, 24 Aug 2026 11:50:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D1=8F=D0=B3=D0=BA=D0=B8=D0=B9=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=20U+00AD:=20=D1=80=D1=83?= =?UTF-8?q?=D1=81=D1=81=D0=BA=D0=B8=D0=B5=20PDF=20=D1=80=D0=B2=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=20=D1=81=D0=BB=D0=BE=D0=B2=D0=B0=20=D0=BF=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Питер и ДМК переносят строку мягким дефисом, а не обычным. Ветка склейки проверяла только "-", поэтому строки соединялись через пробел: «введен ные», «Практиче ски». Теперь U+00AD снимается при склейке, остатки внутри строки удаляются, а в ошибочно опознанных листингах перенос со строкой схлопывается. Измерено на Шоттсе (Питер, 2020, 544 стр.): было 8 мягких переносов на проверенной выборке, стало ноль. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01L2PNJCFFXvizoNjTFuTaqi --- scripts/pdf2html.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/pdf2html.py b/scripts/pdf2html.py index d5763e4..254ee45 100644 --- a/scripts/pdf2html.py +++ b/scripts/pdf2html.py @@ -39,6 +39,7 @@ MAX_IMG_SHARE = 0.6 # доля площади страницы: больше # Запасное опознание листинга, когда издатель вычистил и имена шрифтов, и флаги: # кегль мельче основного текста плюс пунктуация, которой в прозе не бывает. CODEY = re.compile(r"[{}();\[\]<>=*/#]|::|->") +SOFT_HYPHEN = "\u00ad" def style(font, flags=0): @@ -137,7 +138,10 @@ def block_text(b, pre=False): # слова. Ни склейки строк, ни де-дефисации здесь быть не должно. rows = ["".join(span_html(s, plain=True) for s in l["spans"]) for l in b["lines"]] - return "\n".join(rows).rstrip() + # В настоящем коде мягкого переноса не бывает: если он тут есть, блок + # опознан как листинг ошибочно (обычно это таблица опций), и слово надо + # склеить, а не оставить разорванным переводом строки. + return "\n".join(rows).replace(SOFT_HYPHEN + "\n", "").rstrip() out = [] for i, l in enumerate(b["lines"]): line = "".join(span_html(s) for s in l["spans"]) @@ -145,7 +149,12 @@ def block_text(b, pre=False): continue if out: prev = out[-1] - if prev.endswith("-") and not prev.endswith("--"): + # Русские издания переносят мягким дефисом U+00AD, а не обычным: + # без этой ветки строки склеиваются через пробел и слово рвётся + # пополам («введен ные»). Измерено на Шоттсе (Питер, 2020). + if prev.endswith(SOFT_HYPHEN): + out[-1] = prev[:-1] + elif prev.endswith("-") and not prev.endswith("--"): out[-1] = prev[:-1] # de-hyphenate else: out.append(" ") @@ -154,6 +163,8 @@ def block_text(b, pre=False): txt = re.sub(r"(\s*)", r"\1", txt) txt = re.sub(r"(\s*)", r"\1", txt) txt = re.sub(r"(?<=\S) {2,}(?=\S)", " ", txt) + # Мягкие переносы внутри строки читалке не нужны и ломают поиск по тексту. + txt = txt.replace(SOFT_HYPHEN, "") return txt.strip()