From 5ebdf8f9db99a32cc47bcc571ae61ea3a74cfe00 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Wed, 2 Sep 2026 12:58:19 +0300 Subject: [PATCH] =?UTF-8?q?[FIX]=20=D1=83=D0=B7=D0=BA=D0=B8=D0=B5=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BB=D0=BE=D0=BD=D0=BA=D0=B8=20=D1=82=D0=B0=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D1=86=20=D0=BD=D0=B5=20=D1=80=D0=B0=D1=81=D1=82=D1=8F?= =?UTF-8?q?=D0=B3=D0=B8=D0=B2=D0=B0=D1=8E=D1=82=D1=81=D1=8F=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=B2=D1=81=D1=8E=20=D1=88=D0=B8=D1=80=D0=B8=D0=BD=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- md2gost/handlers/table.py | 15 +++++++++++++-- tests/test_render.py | 32 ++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/md2gost/handlers/table.py b/md2gost/handlers/table.py index a46e12e..2d688ca 100644 --- a/md2gost/handlers/table.py +++ b/md2gost/handlers/table.py @@ -38,6 +38,11 @@ _CAPTION_RE = re.compile(r"^\s*Таблица\s+\d+\s*[—–-]+\s*(.+?)\s*$") # узкой колонке LaTeX не может их перенести: строка уезжает за границу колонки # и печатается поверх соседней. _LONG_WORD = 18 + +# Колонка, где самое длинное значение короче этого, в растягивании не нуждается: +# отдав ей равную долю ширины, мы отнимаем место у колонок с текстом, и те +# начинают переноситься по одному слову. +_NARROW_CELL = 16 _BREAK_AFTER = ":/_.-" _ALIGN_BY_STYLE = { @@ -127,8 +132,14 @@ def _tabular(rows: list[list[str]], aligns: list[str]) -> str: row.extend([""] * (cols - len(row))) spec = list(aligns[:cols]) + ["l"] * max(0, cols - len(aligns)) - stretchable = "l" in spec - col_spec = "|".join(_STRETCH if col == "l" else col for col in spec) + widths = [max(len(row[i]) for row in rows) for i in range(cols)] + stretch = [ + align == "l" and width >= _NARROW_CELL for align, width in zip(spec, widths) + ] + stretchable = any(stretch) + col_spec = "|".join( + _STRETCH if is_wide else col for col, is_wide in zip(spec, stretch) + ) env = "tabularx" if stretchable else "tabular" width = "{\\textwidth}" if stretchable else "" diff --git a/tests/test_render.py b/tests/test_render.py index 4aa911f..f32d536 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -394,16 +394,16 @@ def test_wide_table_uses_tabularx_so_it_fits_the_page() -> None: def test_table_left_columns_become_stretchable() -> None: + """Растягиваются колонки с текстом; «Сценарий» короткая и остаётся узкой.""" tex = render(WIDE_TABLE_MD) - assert tex.count(">{\\raggedright\\arraybackslash}X") == 3 + assert tex.count(">{\\raggedright\\arraybackslash}X") == 2 def test_table_keeps_center_columns_narrow() -> None: - """Числовые колонки не должны растягиваться — растягивается только текст.""" - tex = render(TABLE_MD) - assert "\\begin{tabularx}{\\textwidth}" in tex - assert tex.count(">{\\raggedright\\arraybackslash}X") == 1 - assert f"{{|{_STRETCH}|c|r|}}" in tex + """Все колонки короткие: растягивать нечего, таблица идёт по содержимому.""" + tex = body(render(TABLE_MD)) + assert "\\begin{tabular}{|l|c|r|}" in tex + assert "\\begin{tabularx}" not in tex def test_table_without_left_columns_stays_plain_tabular() -> None: @@ -440,3 +440,23 @@ def test_break_points_do_not_touch_latex_commands() -> None: ) assert "\\textbf{" in tex assert "\\textbf\\allowbreak" not in tex + + +MIXED_WIDTH_TABLE_MD = ( + "| Сценарий | Что делает |\n" + "| :--- | :--- |\n" + "| build.yml | Собирает образ Docker целиком и публикует его в реестр |\n" + "| test.yml | Собирает проект через CMake и прогоняет набор тестов |\n" +) + + +def test_narrow_column_is_not_stretched() -> None: + """Колонка из коротких значений не должна занимать половину ширины.""" + tex = body(render(MIXED_WIDTH_TABLE_MD)) + assert f"{{|l|{_STRETCH}|}}" in tex + + +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