diff --git a/md2gost/handlers/text.py b/md2gost/handlers/text.py index 19999ee..082c14f 100644 --- a/md2gost/handlers/text.py +++ b/md2gost/handlers/text.py @@ -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}}" diff --git a/md2gost/latex/preamble.py b/md2gost/latex/preamble.py index 10af761..9443a33 100644 --- a/md2gost/latex/preamble.py +++ b/md2gost/latex/preamble.py @@ -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 diff --git a/md2gost/latex/titlepages/ptp_report.py b/md2gost/latex/titlepages/ptp_report.py index d321d7d..52eaaf7 100644 --- a/md2gost/latex/titlepages/ptp_report.py +++ b/md2gost/latex/titlepages/ptp_report.py @@ -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" diff --git a/tests/test_render.py b/tests/test_render.py index f32d536..407fa40 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -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