[FIX] широкие таблицы переносятся по словам и не вылезают за поле
This commit is contained in:
@@ -80,18 +80,36 @@ def _collect_rows(
|
||||
return pos, rows, aligns
|
||||
|
||||
|
||||
_STRETCH = ">{\\raggedright\\arraybackslash}X"
|
||||
|
||||
|
||||
def _tabular(rows: list[list[str]], aligns: list[str]) -> str:
|
||||
"""Табличное окружение для строк с заданным выравниванием колонок.
|
||||
|
||||
Колонка, выровненная по левому краю, считается текстовой: её содержимое
|
||||
должно переноситься по словам, иначе широкая таблица уезжает за правое
|
||||
поле страницы. Такие колонки верстаются растягиваемым типом ``X``, а вся
|
||||
таблица — окружением ``tabularx`` шириной в текстовое поле. Колонки по
|
||||
центру и по правому краю (обычно числовые) остаются узкими.
|
||||
|
||||
Если текстовых колонок нет, растягивать нечего и используется обычный
|
||||
``tabular``: ``tabularx`` без единой ``X``-колонки не собирается.
|
||||
"""
|
||||
cols = max(len(row) for row in rows)
|
||||
for row in rows:
|
||||
row.extend([""] * (cols - len(row)))
|
||||
|
||||
spec = list(aligns[:cols]) + ["l"] * max(0, cols - len(aligns))
|
||||
col_spec = "|".join(spec)
|
||||
lines = [f"\\begin{{tabular}}{{|{col_spec}|}}", "\\hline"]
|
||||
stretchable = "l" in spec
|
||||
col_spec = "|".join(_STRETCH if col == "l" else col for col in spec)
|
||||
|
||||
env = "tabularx" if stretchable else "tabular"
|
||||
width = "{\\textwidth}" if stretchable else ""
|
||||
lines = [f"\\begin{{{env}}}{width}{{|{col_spec}|}}", "\\hline"]
|
||||
for row in rows:
|
||||
lines.append(" & ".join(row) + " \\\\")
|
||||
lines.append("\\hline")
|
||||
lines.append("\\end{tabular}")
|
||||
lines.append(f"\\end{{{env}}}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
|
||||
+42
-2
@@ -1,5 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from md2gost.handlers.table import _STRETCH
|
||||
from md2gost.latex.titlepages import TITLEPAGES
|
||||
from md2gost.parser import Parser
|
||||
from md2gost.render import Renderer
|
||||
@@ -12,6 +13,11 @@ def render(md: str) -> str:
|
||||
return Renderer(parser.tokens, parser.front_matter).render()
|
||||
|
||||
|
||||
def body(tex: str) -> str:
|
||||
"""Тело документа без преамбулы: в преамбуле свои tabularx-макросы."""
|
||||
return tex.split("\\setcounter{page}{2}", 1)[1]
|
||||
|
||||
|
||||
def render_fm(extra: str, body: str = "Текст.\n") -> str:
|
||||
head = f"---\nназвание: Тестовая работа\nтип: Отчёт\n{extra}---\n\n"
|
||||
parser = Parser(head + body)
|
||||
@@ -123,7 +129,7 @@ def test_table_with_caption() -> None:
|
||||
tex = render(TABLE_MD)
|
||||
assert "\\begin{table}[H]" in tex
|
||||
assert "\\caption{Сравнение скорости}" in tex
|
||||
assert "\\begin{tabular}{|l|c|r|}" in tex
|
||||
assert "\\begin{tabularx}{\\textwidth}" in tex
|
||||
assert "\\textbf{1} & 0.027852 & 0.000285 \\\\" in tex
|
||||
|
||||
|
||||
@@ -136,7 +142,7 @@ def test_table_caption_number_is_discarded() -> None:
|
||||
def test_table_without_caption_stays_bare() -> None:
|
||||
tex = render("| a | b |\n| --- | --- |\n| 1 | 2 |\n")
|
||||
assert "\\begin{table}" not in tex
|
||||
assert "\\begin{tabular}{|l|l|}" in tex
|
||||
assert "\\begin{tabularx}{\\textwidth}" in tex
|
||||
|
||||
|
||||
def test_table_caption_paragraph_is_not_duplicated() -> None:
|
||||
@@ -365,3 +371,37 @@ def test_listing_unsupported_language_falls_back_to_plain() -> None:
|
||||
tex = render("```yaml\nkey: value\n```\n")
|
||||
assert "language=" not in tex
|
||||
assert "key: value" in tex
|
||||
|
||||
|
||||
WIDE_TABLE_MD = (
|
||||
"Таблица 1 —— Сценарии интеграции\n\n"
|
||||
"| Сценарий | Событие | Что делает |\n"
|
||||
"| :--- | :--- | :--- |\n"
|
||||
"| build.yml | отправка изменений | Собирает образ Docker целиком |\n"
|
||||
)
|
||||
|
||||
|
||||
def test_wide_table_uses_tabularx_so_it_fits_the_page() -> None:
|
||||
"""Колонки с текстом должны переноситься, а не вылезать за поле."""
|
||||
tex = render(WIDE_TABLE_MD)
|
||||
assert "\\begin{tabularx}{\\textwidth}" in tex
|
||||
assert "\\begin{tabular}{" not in tex
|
||||
|
||||
|
||||
def test_table_left_columns_become_stretchable() -> None:
|
||||
tex = render(WIDE_TABLE_MD)
|
||||
assert tex.count(">{\\raggedright\\arraybackslash}X") == 3
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
def test_table_without_left_columns_stays_plain_tabular() -> None:
|
||||
tex = body(render("| a | b |\n| :---: | :---: |\n| 1 | 2 |\n"))
|
||||
assert "\\begin{tabular}{|c|c|}" in tex
|
||||
assert "\\begin{tabularx}" not in tex
|
||||
|
||||
Reference in New Issue
Block a user