From 82cde7b94b5764e40eb51100a27457bb8930e9ec Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Wed, 2 Sep 2026 13:11:56 +0300 Subject: [PATCH] =?UTF-8?q?[FIX]=20=D0=BE=D1=82=D0=B1=D0=B8=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B7=D0=B0=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2,=20=D0=BC=D0=B0=D1=80=D0=BA=D0=B5=D1=80=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=BD=D0=BE=D1=81=D0=B0=20=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BA=20=D0=BA=D0=BE=D0=B4=D0=B0,=20=D0=BD=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D1=80=D1=8B=D0=B2=D0=BD=D1=8B=D0=B5=20=D0=B8=D0=BD=D0=B8?= =?UTF-8?q?=D1=86=D0=B8=D0=B0=D0=BB=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- md2gost/handlers/inline.py | 19 ++++++++++++++++++- md2gost/latex/preamble.py | 13 ++++++++----- tests/test_render.py | 11 +++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/md2gost/handlers/inline.py b/md2gost/handlers/inline.py index fbf51c6..8016ab4 100644 --- a/md2gost/handlers/inline.py +++ b/md2gost/handlers/inline.py @@ -6,6 +6,7 @@ from __future__ import annotations +import re import sys from markdown_it.token import Token @@ -32,9 +33,25 @@ def escape_latex(text: str) -> str: return text.translate(_LATEX_SPECIAL) +# Инициалы не должны отрываться друг от друга и от фамилии переносом строки: +# «/ И.» на одной строке и «В. Гилев» на следующей — ошибка оформления списка +# источников. Связывается одиночная заглавная буква с точкой и следующее слово, +# начинающееся с заглавной. +_INITIALS_RE = re.compile(r"(? str: + """Заменить пробел после инициала на неразрывный.""" + previous = None + while previous != text: + previous = text + text = _INITIALS_RE.sub(r"\1~", text) + return text + + @inline("text") def _text(tok: Token) -> str: - return escape_latex(tok.content) + return bind_initials(escape_latex(tok.content)) @inline("strong_open") diff --git a/md2gost/latex/preamble.py b/md2gost/latex/preamble.py index 793ea74..f07bb5d 100644 --- a/md2gost/latex/preamble.py +++ b/md2gost/latex/preamble.py @@ -58,7 +58,7 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle} % комментарий распадался бы на прямые русские и курсивные латинские слова. commentstyle=\color{lstcomment}, stringstyle=\color{lststring}, - numberstyle=\tiny\color{lstlineno}, + numberstyle=\scriptsize\color{lstlineno}, identifierstyle=, breakatwhitespace=false, breaklines=true, @@ -67,7 +67,10 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle} frame=single, keepspaces=true, numbers=left, - numbersep=5pt, + numbersep=7pt, + aboveskip=0.7\baselineskip, + belowskip=0.4\baselineskip, + postbreak=\mbox{\textcolor{lstlineno}{$\hookrightarrow$}\space}, xleftmargin=25pt, xrightmargin=25pt, showspaces=false, @@ -91,9 +94,9 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle} \titleformat{\section}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesection. } \titleformat{\subsection}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesubsection. } \titleformat{\subsubsection}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesubsubsection. } -\titlespacing*{\section}{1.25cm}{0.5ex plus 0.2ex minus 0.2ex}{0.3ex plus 0.1ex minus 0.1ex} -\titlespacing*{\subsection}{1.25cm}{0.5ex plus 0.2ex minus 0.2ex}{0.3ex plus 0.1ex minus 0.1ex} -\titlespacing*{\subsubsection}{1.25cm}{0.5ex plus 0.2ex minus 0.2ex}{0.3ex plus 0.1ex minus 0.1ex} +\titlespacing*{\section}{1.25cm}{1ex plus 0.3ex minus 0.2ex}{0.6ex plus 0.2ex minus 0.1ex} +\titlespacing*{\subsection}{1.25cm}{1ex plus 0.3ex minus 0.2ex}{0.6ex plus 0.2ex minus 0.1ex} +\titlespacing*{\subsubsection}{1.25cm}{1ex plus 0.3ex minus 0.2ex}{0.6ex plus 0.2ex minus 0.1ex} \usepackage{tocloft} \addto\captionsrussian{% \renewcommand{\contentsname}{СОДЕРЖАНИЕ}% diff --git a/tests/test_render.py b/tests/test_render.py index 4641823..d6107a0 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -498,3 +498,14 @@ def test_bare_listing_does_not_float() -> None: """Фрагмент без подписи — часть абзаца, ему плавать незачем.""" tex = body(render("```cpp\nint x;\n```\n")) assert "float=" not in tex + + +def test_initials_are_not_split_across_lines() -> None: + """«/ И.» на одной строке и «В. Гилев» на следующей — ошибка оформления.""" + tex = body(render("Гилев, И. В. Использование технологии SDR.\n")) + assert "И.~В.~Использование" in tex + + +def test_lowercase_abbreviation_is_left_alone() -> None: + tex = body(render("В 3 т., Воронеж, 2025.\n")) + assert "т.~Воронеж" not in tex