[FIX] длинные токены в таблицах переносятся, а не налезают на соседнюю колонку
This commit is contained in:
@@ -33,6 +33,13 @@ from md2gost.registry import block, pattern
|
|||||||
|
|
||||||
_CAPTION_RE = re.compile(r"^\s*Таблица\s+\d+\s*[—–-]+\s*(.+?)\s*$")
|
_CAPTION_RE = re.compile(r"^\s*Таблица\s+\d+\s*[—–-]+\s*(.+?)\s*$")
|
||||||
|
|
||||||
|
# Длина слова, начиная с которой ему нужны точки разрыва. Идентификаторы вроде
|
||||||
|
# HackRFTestingServer:идентификатор не содержат пробелов и дефисов, поэтому в
|
||||||
|
# узкой колонке LaTeX не может их перенести: строка уезжает за границу колонки
|
||||||
|
# и печатается поверх соседней.
|
||||||
|
_LONG_WORD = 18
|
||||||
|
_BREAK_AFTER = ":/_.-"
|
||||||
|
|
||||||
_ALIGN_BY_STYLE = {
|
_ALIGN_BY_STYLE = {
|
||||||
"text-align:left": "l",
|
"text-align:left": "l",
|
||||||
"text-align:center": "c",
|
"text-align:center": "c",
|
||||||
@@ -40,6 +47,26 @@ _ALIGN_BY_STYLE = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _breakable(cell: str) -> str:
|
||||||
|
"""Расставить точки переноса внутри длинных слов ячейки.
|
||||||
|
|
||||||
|
Ячейка уже отрендерена в LaTeX, поэтому слова с обратной косой чертой или
|
||||||
|
фигурными скобками пропускаются: вставка внутрь имени команды сломала бы её.
|
||||||
|
"""
|
||||||
|
words = []
|
||||||
|
for word in cell.split(" "):
|
||||||
|
if len(word) < _LONG_WORD or any(ch in word for ch in "\\{}"):
|
||||||
|
words.append(word)
|
||||||
|
continue
|
||||||
|
out = []
|
||||||
|
for ch in word:
|
||||||
|
out.append(ch)
|
||||||
|
if ch in _BREAK_AFTER:
|
||||||
|
out.append("\\allowbreak ")
|
||||||
|
words.append("".join(out))
|
||||||
|
return " ".join(words)
|
||||||
|
|
||||||
|
|
||||||
def _cell_align(tok: Token) -> str:
|
def _cell_align(tok: Token) -> str:
|
||||||
style = str(tok.attrGet("style") or "").replace(" ", "")
|
style = str(tok.attrGet("style") or "").replace(" ", "")
|
||||||
return _ALIGN_BY_STYLE.get(style, "l")
|
return _ALIGN_BY_STYLE.get(style, "l")
|
||||||
@@ -69,7 +96,7 @@ def _collect_rows(
|
|||||||
pos += 1
|
pos += 1
|
||||||
break
|
break
|
||||||
if ctok.type in ("th_open", "td_open"):
|
if ctok.type in ("th_open", "td_open"):
|
||||||
row.append(render_inline(tokens[pos + 1]))
|
row.append(_breakable(render_inline(tokens[pos + 1])))
|
||||||
row_aligns.append(_cell_align(ctok))
|
row_aligns.append(_cell_align(ctok))
|
||||||
pos += 3
|
pos += 3
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
|
|||||||
\usepackage{float}
|
\usepackage{float}
|
||||||
\usepackage{wrapfig}
|
\usepackage{wrapfig}
|
||||||
\sloppy
|
\sloppy
|
||||||
|
\setlength{\emergencystretch}{2em}
|
||||||
\clubpenalty=10000
|
\clubpenalty=10000
|
||||||
\widowpenalty=10000
|
\widowpenalty=10000
|
||||||
\usepackage{enumitem}
|
\usepackage{enumitem}
|
||||||
|
|||||||
@@ -410,3 +410,33 @@ def test_table_without_left_columns_stays_plain_tabular() -> None:
|
|||||||
tex = body(render("| a | b |\n| :---: | :---: |\n| 1 | 2 |\n"))
|
tex = body(render("| a | b |\n| :---: | :---: |\n| 1 | 2 |\n"))
|
||||||
assert "\\begin{tabular}{|c|c|}" in tex
|
assert "\\begin{tabular}{|c|c|}" in tex
|
||||||
assert "\\begin{tabularx}" not in tex
|
assert "\\begin{tabularx}" not in tex
|
||||||
|
|
||||||
|
|
||||||
|
LONG_TOKEN_TABLE_MD = (
|
||||||
|
"| Направление | Формат | Назначение |\n"
|
||||||
|
"| :--- | :--- | :--- |\n"
|
||||||
|
"| сервер | HackRFTestingServer:идентификатор | Приветствие, подтверждает |\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_long_token_in_cell_gets_break_points() -> None:
|
||||||
|
"""Иначе токен не переносится и печатается поверх соседней колонки."""
|
||||||
|
tex = body(render(LONG_TOKEN_TABLE_MD))
|
||||||
|
assert "HackRFTestingServer:\\allowbreak" in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_short_cells_are_left_alone() -> None:
|
||||||
|
tex = body(render("| a | b |\n| :--- | :--- |\n| ping | сервер |\n"))
|
||||||
|
assert "\\allowbreak" not in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_break_points_do_not_touch_latex_commands() -> None:
|
||||||
|
"""В ячейке с разметкой есть команды; ломать их вставками нельзя."""
|
||||||
|
tex = body(
|
||||||
|
render(
|
||||||
|
"| Поле | Значение |\n| :--- | :--- |\n"
|
||||||
|
"| **оченьдлинноежирноеслово_подчёркивание** | x |\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert "\\textbf{" in tex
|
||||||
|
assert "\\textbf\\allowbreak" not in tex
|
||||||
|
|||||||
Reference in New Issue
Block a user