[FIX] узкие колонки таблиц не растягиваются на всю ширину

This commit is contained in:
Arseny
2026-09-02 12:58:19 +03:00
parent f426e865b5
commit 5ebdf8f9db
2 changed files with 39 additions and 8 deletions
+13 -2
View File
@@ -38,6 +38,11 @@ _CAPTION_RE = re.compile(r"^\s*Таблица\s+\d+\s*[—–-]+\s*(.+?)\s*$")
# узкой колонке LaTeX не может их перенести: строка уезжает за границу колонки # узкой колонке LaTeX не может их перенести: строка уезжает за границу колонки
# и печатается поверх соседней. # и печатается поверх соседней.
_LONG_WORD = 18 _LONG_WORD = 18
# Колонка, где самое длинное значение короче этого, в растягивании не нуждается:
# отдав ей равную долю ширины, мы отнимаем место у колонок с текстом, и те
# начинают переноситься по одному слову.
_NARROW_CELL = 16
_BREAK_AFTER = ":/_.-" _BREAK_AFTER = ":/_.-"
_ALIGN_BY_STYLE = { _ALIGN_BY_STYLE = {
@@ -127,8 +132,14 @@ def _tabular(rows: list[list[str]], aligns: list[str]) -> str:
row.extend([""] * (cols - len(row))) row.extend([""] * (cols - len(row)))
spec = list(aligns[:cols]) + ["l"] * max(0, cols - len(aligns)) spec = list(aligns[:cols]) + ["l"] * max(0, cols - len(aligns))
stretchable = "l" in spec widths = [max(len(row[i]) for row in rows) for i in range(cols)]
col_spec = "|".join(_STRETCH if col == "l" else col for col in spec) 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" env = "tabularx" if stretchable else "tabular"
width = "{\\textwidth}" if stretchable else "" width = "{\\textwidth}" if stretchable else ""
+26 -6
View File
@@ -394,16 +394,16 @@ def test_wide_table_uses_tabularx_so_it_fits_the_page() -> None:
def test_table_left_columns_become_stretchable() -> None: def test_table_left_columns_become_stretchable() -> None:
"""Растягиваются колонки с текстом; «Сценарий» короткая и остаётся узкой."""
tex = render(WIDE_TABLE_MD) 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: def test_table_keeps_center_columns_narrow() -> None:
"""Числовые колонки не должны растягиваться — растягивается только текст.""" """Все колонки короткие: растягивать нечего, таблица идёт по содержимому."""
tex = render(TABLE_MD) tex = body(render(TABLE_MD))
assert "\\begin{tabularx}{\\textwidth}" in tex assert "\\begin{tabular}{|l|c|r|}" in tex
assert tex.count(">{\\raggedright\\arraybackslash}X") == 1 assert "\\begin{tabularx}" not in tex
assert f"{{|{_STRETCH}|c|r|}}" in tex
def test_table_without_left_columns_stays_plain_tabular() -> None: 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{" in tex
assert "\\textbf\\allowbreak" not 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