[FIX] шапка титульника, ширина номера в оглавлении и перечень сокращений в пределах поля

This commit is contained in:
Arseny
2026-09-02 13:03:05 +03:00
parent 5ebdf8f9db
commit c765892d7d
4 changed files with 52 additions and 9 deletions
+7 -2
View File
@@ -39,9 +39,14 @@ def abbreviations(text: str) -> str:
for abbr, desc in rows:
pad = max_abbr - len(abbr) + 2
tabular_rows.append(
f"{abbr} {' ' * pad}& \\hangafter=1\\hangindent=2em ------ {desc} \\\\"
f"{abbr} {' ' * pad}& \\hangafter=1\\hangindent=2em --- {desc} \\\\"
)
col_spec = f"@{{\\hspace{{0pt}}}}p{{{abbr_col}em}}@{{\\hspace{{0pt}}}}p{{\\dimexpr\\linewidth-{abbr_col}em\\relax}}"
# Отбивки колонок убраны с обеих сторон и между ними: иначе сумма ширин
# превышает \linewidth на 2\tabcolsep и перечень выходит за правое поле.
col_spec = (
f"@{{\\hspace{{0pt}}}}p{{{abbr_col}em}}"
f"@{{}}p{{\\dimexpr\\linewidth-{abbr_col}em\\relax}}@{{\\hspace{{0pt}}}}"
)
body = "\n".join(tabular_rows)
return f"\\noindent\\begin{{tabular}}{{{col_spec}}}\n{body}\n\\end{{tabular}}"
+21 -4
View File
@@ -84,12 +84,15 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
\renewcommand{\cftsecpagefont}{\mdseries}
\renewcommand{\cftsubsecfont}{\mdseries}
\renewcommand{\cftsubsubsecfont}{\mdseries}
% Ширина поля номера в оглавлении измеряется по шрифту, а не задаётся
% константой: при фиксированных 1.5em номер 2.10. не помещается и печатается
% поверх названия главы, а у остальных пропадает пробел после точки.
\setlength{\cftsecindent}{0em}
\setlength{\cftsecnumwidth}{1em}
\setlength{\cftsubsecindent}{0em}
\setlength{\cftsubsecnumwidth}{1.5em}
\setlength{\cftsubsubsecindent}{0em}
\setlength{\cftsubsubsecnumwidth}{2.1em}
\settowidth{\cftsecnumwidth}{\cftsecfont 9.\enspace}
\settowidth{\cftsubsecnumwidth}{\cftsubsecfont 9.99.\enspace}
\settowidth{\cftsubsubsecnumwidth}{\cftsubsubsecfont 9.99.99.\enspace}
\newcommand{\sigline}[3][4cm]{%
\begin{tabular}[t]{@{}c@{}}%
@@ -99,6 +102,17 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
\end{tabular}%
}
% Ширины шапки титульного листа. Колонка эмблемы задаётся явно, ширина
% текстовой части — остаток от текстового поля за вычетом рамки и отбивок,
% поэтому шапка не может вылезти за рамку при смене полей страницы.
\newlength{\ptpemblemwidth}
\newlength{\ptpheadwidth}
\newlength{\ptpheadpad}
\setlength{\ptpemblemwidth}{0.14\textwidth}
\setlength{\ptpheadpad}{4pt}
\setlength{\ptpheadwidth}{%
\dimexpr\textwidth-\ptpemblemwidth-4\ptpheadpad-3\arrayrulewidth\relax}
\newcommand{\ptpfieldw}[4][4.5cm]{%
\par\noindent
\makebox[#1][l]{#2}%
@@ -113,7 +127,10 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
\newcommand{\ptpfieldnote}[4][4.5cm]{%
\ptpfield[#1]{#2}{#3}%
\par\vspace{-0.45em}%
\hspace*{#1}\makebox[\dimexpr\textwidth-#1\relax][c]{\footnotesize\itshape #4}\par}
% \noindent обязателен: иначе к строке подписи прибавляется абзацный отступ,
% и она ровно на \parindent выходит за правое поле.
\noindent\hspace*{#1}%
\makebox[\dimexpr\textwidth-#1\relax][c]{\footnotesize\itshape #4}\par}
\newcommand{\ptpfieldpar}[3][4.5cm]{%
\par\noindent
+4 -3
View File
@@ -27,13 +27,14 @@ def render(fm: dict[str, str]) -> str:
"% --- Шапка в рамке с разделителем, как в бланке ---\n"
"\\vspace*{-45pt}\n"
"\\noindent\\begin{tabular}"
"{|@{\\hspace{4pt}}c@{\\hspace{4pt}}|@{\\hspace{4pt}}c@{\\hspace{4pt}}|}\n"
"{|@{\\hspace{\\ptpheadpad}}c@{\\hspace{\\ptpheadpad}}"
"|@{\\hspace{\\ptpheadpad}}c@{\\hspace{\\ptpheadpad}}|}\n"
"\\hline\n"
"\\begin{minipage}{0.16\\textwidth}\\centering\\vspace{3pt}\n"
"\\begin{minipage}{\\ptpemblemwidth}\\centering\\vspace{3pt}\n"
"\\includegraphics[width=0.92\\textwidth]{emblem}\n"
"\\vspace{3pt}\\end{minipage}\n"
"&\n"
"\\begin{minipage}{0.775\\textwidth}\\small\\bfseries\n"
"\\begin{minipage}{\\ptpheadwidth}\\small\\bfseries\n"
"\\vspace*{2pt}\n"
f"{ministry_lines(fm)}\n"
"\\vspace*{0.5ex}\n"
+20
View File
@@ -460,3 +460,23 @@ def test_all_short_columns_stay_plain_tabular() -> None:
tex = body(render("| a | b |\n| :--- | :--- |\n| ping | сервер |\n"))
assert "\\begin{tabular}{|l|l|}" in tex
assert "\\begin{tabularx}" not in tex
ABBR_MD = (
"# ПЕРЕЧЕНЬ ПРИНЯТЫХ СОКРАЩЕНИЙ\n\n"
"SDR — Software-Defined Radio — программно-определяемая радиосистема\n"
"PSO — Particle Swarm Optimisation — метод роевой оптимизации\n"
)
def test_abbreviation_dash_is_single() -> None:
"""Шесть дефисов дают в LaTeX два длинных тире подряд вместо одного."""
tex = body(render(ABBR_MD))
assert "------" not in tex
assert "--- Software-Defined Radio" in tex
def test_abbreviation_table_has_no_extra_column_padding() -> None:
"""Отбивка между колонками добавляется к \\linewidth и роняет строку за поле."""
tex = body(render(ABBR_MD))
assert "@{}p{\\dimexpr\\linewidth" in tex