[FIX] отбивки заголовков, маркер переноса строк кода, неразрывные инициалы

This commit is contained in:
Arseny
2026-09-02 13:11:56 +03:00
parent 2a0333c673
commit 82cde7b94b
3 changed files with 37 additions and 6 deletions
+18 -1
View File
@@ -6,6 +6,7 @@
from __future__ import annotations from __future__ import annotations
import re
import sys import sys
from markdown_it.token import Token from markdown_it.token import Token
@@ -32,9 +33,25 @@ def escape_latex(text: str) -> str:
return text.translate(_LATEX_SPECIAL) return text.translate(_LATEX_SPECIAL)
# Инициалы не должны отрываться друг от друга и от фамилии переносом строки:
# «/ И.» на одной строке и «В. Гилев» на следующей — ошибка оформления списка
# источников. Связывается одиночная заглавная буква с точкой и следующее слово,
# начинающееся с заглавной.
_INITIALS_RE = re.compile(r"(?<![\w.])([A-ZА-ЯЁ]\.)\s+(?=[A-ZА-ЯЁ])")
def bind_initials(text: str) -> str:
"""Заменить пробел после инициала на неразрывный."""
previous = None
while previous != text:
previous = text
text = _INITIALS_RE.sub(r"\1~", text)
return text
@inline("text") @inline("text")
def _text(tok: Token) -> str: def _text(tok: Token) -> str:
return escape_latex(tok.content) return bind_initials(escape_latex(tok.content))
@inline("strong_open") @inline("strong_open")
+8 -5
View File
@@ -58,7 +58,7 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
% комментарий распадался бы на прямые русские и курсивные латинские слова. % комментарий распадался бы на прямые русские и курсивные латинские слова.
commentstyle=\color{lstcomment}, commentstyle=\color{lstcomment},
stringstyle=\color{lststring}, stringstyle=\color{lststring},
numberstyle=\tiny\color{lstlineno}, numberstyle=\scriptsize\color{lstlineno},
identifierstyle=, identifierstyle=,
breakatwhitespace=false, breakatwhitespace=false,
breaklines=true, breaklines=true,
@@ -67,7 +67,10 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
frame=single, frame=single,
keepspaces=true, keepspaces=true,
numbers=left, numbers=left,
numbersep=5pt, numbersep=7pt,
aboveskip=0.7\baselineskip,
belowskip=0.4\baselineskip,
postbreak=\mbox{\textcolor{lstlineno}{$\hookrightarrow$}\space},
xleftmargin=25pt, xleftmargin=25pt,
xrightmargin=25pt, xrightmargin=25pt,
showspaces=false, showspaces=false,
@@ -91,9 +94,9 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
\titleformat{\section}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesection. } \titleformat{\section}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesection. }
\titleformat{\subsection}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesubsection. } \titleformat{\subsection}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesubsection. }
\titleformat{\subsubsection}{\fontsize{14pt}{18pt}\selectfont\bfseries}{}{0em}{\thesubsubsection. } \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*{\section}{1.25cm}{1ex plus 0.3ex minus 0.2ex}{0.6ex plus 0.2ex minus 0.1ex}
\titlespacing*{\subsection}{1.25cm}{0.5ex plus 0.2ex minus 0.2ex}{0.3ex plus 0.1ex 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}{0.5ex plus 0.2ex minus 0.2ex}{0.3ex plus 0.1ex minus 0.1ex} \titlespacing*{\subsubsection}{1.25cm}{1ex plus 0.3ex minus 0.2ex}{0.6ex plus 0.2ex minus 0.1ex}
\usepackage{tocloft} \usepackage{tocloft}
\addto\captionsrussian{% \addto\captionsrussian{%
\renewcommand{\contentsname}{СОДЕРЖАНИЕ}% \renewcommand{\contentsname}{СОДЕРЖАНИЕ}%
+11
View File
@@ -498,3 +498,14 @@ def test_bare_listing_does_not_float() -> None:
"""Фрагмент без подписи — часть абзаца, ему плавать незачем.""" """Фрагмент без подписи — часть абзаца, ему плавать незачем."""
tex = body(render("```cpp\nint x;\n```\n")) tex = body(render("```cpp\nint x;\n```\n"))
assert "float=" not in tex 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