[FIX] перечень сокращений: до тире обычный пробел, разбор пометок в подписи рисунка
Колонка аббревиатур больше не считается на глаз: обычная колонка l берёт ширину по самой длинной аббревиатуре, тире и пробелы вокруг него ушли в разделитель колонок. Расшифровка целиком лежит в колонке X, поэтому её перенос по-прежнему встаёт под первым словом расшифровки. Подпись рисунка не проходит через инлайн-рендер, и пометка ==текст== в ней печаталась как есть. Разбор пометок вынесен в render_marked и вызывается из обработчика рисунка.
This commit is contained in:
@@ -30,7 +30,7 @@ from urllib.parse import unquote
|
|||||||
|
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
|
|
||||||
from md2gost.handlers.inline import escape_latex
|
from md2gost.handlers.inline import escape_latex, render_marked
|
||||||
from md2gost.registry import pattern
|
from md2gost.registry import pattern
|
||||||
|
|
||||||
DEFAULT_WIDTH = 0.8
|
DEFAULT_WIDTH = 0.8
|
||||||
@@ -93,7 +93,7 @@ def figure(tokens: list[Token]) -> str:
|
|||||||
if len(tokens) >= 5:
|
if len(tokens) >= 5:
|
||||||
m = _CAPTION_RE.match(tokens[4].content)
|
m = _CAPTION_RE.match(tokens[4].content)
|
||||||
if m:
|
if m:
|
||||||
caption = escape_latex(m.group(1))
|
caption = render_marked(m.group(1), escape_latex)
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
"\\begin{figure}[htb]",
|
"\\begin{figure}[htb]",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
|
|
||||||
@@ -114,18 +115,27 @@ def highlight(text: str) -> str:
|
|||||||
return " ".join(highlight_word(word) for word in escaped.split(" ") if word)
|
return " ".join(highlight_word(word) for word in escaped.split(" ") if word)
|
||||||
|
|
||||||
|
|
||||||
@inline("text")
|
def render_marked(text: str, plain: Callable[[str], str] = render_text) -> str:
|
||||||
def _text(tok: Token) -> str:
|
"""Разобрать пометки правок, остальное отдать ``plain``.
|
||||||
|
|
||||||
|
Подпись рисунка не проходит через инлайн-рендер, но выделять правки
|
||||||
|
нужно и в ней, поэтому разбор вынесен из обработчика текстового узла.
|
||||||
|
"""
|
||||||
parts: list[str] = []
|
parts: list[str] = []
|
||||||
end = 0
|
end = 0
|
||||||
for match in _MARK_RE.finditer(tok.content):
|
for match in _MARK_RE.finditer(text):
|
||||||
parts.append(render_text(tok.content[end : match.start()]))
|
parts.append(plain(text[end : match.start()]))
|
||||||
parts.append(highlight(match.group(1)))
|
parts.append(highlight(match.group(1)))
|
||||||
end = match.end()
|
end = match.end()
|
||||||
parts.append(render_text(tok.content[end:]))
|
parts.append(plain(text[end:]))
|
||||||
return "".join(parts)
|
return "".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
@inline("text")
|
||||||
|
def _text(tok: Token) -> str:
|
||||||
|
return render_marked(tok.content)
|
||||||
|
|
||||||
|
|
||||||
@inline("strong_open")
|
@inline("strong_open")
|
||||||
def _strong_open(tok: Token) -> str:
|
def _strong_open(tok: Token) -> str:
|
||||||
return r"\textbf{"
|
return r"\textbf{"
|
||||||
|
|||||||
+11
-18
@@ -33,23 +33,16 @@ def abbreviations(text: str) -> str:
|
|||||||
if not rows:
|
if not rows:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
max_abbr = max(len(r[0]) for r in rows)
|
# Колонка l сама берёт ширину самой длинной аббревиатуры, поэтому тире
|
||||||
# На прописную букву в Times уходит около 0,75em; плюс отбивка перед тире.
|
# выстраиваются в столбец без подсчёта ширин на глаз, а отбивка до тире
|
||||||
# Прежняя оценка в 1em на символ отодвигала тире от аббревиатуры почти на
|
# остаётся обычным пробелом. Расшифровка целиком лежит в колонке X, и её
|
||||||
# треть строки.
|
# перенос встаёт под первым словом расшифровки, а не под тире.
|
||||||
abbr_col = round(max_abbr * 0.75 + 0.8, 2)
|
body = "\n".join(f"{abbr} & {desc} \\\\" for abbr, desc in rows)
|
||||||
tabular_rows = []
|
|
||||||
for abbr, desc in rows:
|
|
||||||
pad = max_abbr - len(abbr) + 2
|
|
||||||
tabular_rows.append(
|
|
||||||
f"{abbr} {' ' * pad}& \\hangafter=1\\hangindent=2em --- {desc} \\\\"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Отбивки колонок убраны с обеих сторон и между ними: иначе сумма ширин
|
# Отбивки колонок убраны с обоих краёв: иначе сумма ширин превышает
|
||||||
# превышает \linewidth на 2\tabcolsep и перечень выходит за правое поле.
|
# \linewidth на 2\tabcolsep и перечень выходит за правое поле.
|
||||||
col_spec = (
|
return (
|
||||||
f"@{{\\hspace{{0pt}}}}p{{{abbr_col}em}}"
|
"\\noindent\\begin{tabularx}{\\linewidth}{@{}l@{\\ ---\\ }X@{}}\n"
|
||||||
f"@{{}}p{{\\dimexpr\\linewidth-{abbr_col}em\\relax}}@{{\\hspace{{0pt}}}}"
|
f"{body}\n"
|
||||||
|
"\\end{tabularx}"
|
||||||
)
|
)
|
||||||
body = "\n".join(tabular_rows)
|
|
||||||
return f"\\noindent\\begin{{tabular}}{{{col_spec}}}\n{body}\n\\end{{tabular}}"
|
|
||||||
|
|||||||
+14
-2
@@ -50,6 +50,11 @@ def test_mark_splits_compound_word_into_separate_boxes() -> None:
|
|||||||
assert "\\hlw{аппаратно}\\hlw{-}\\allowbreak \\hlw{программный}" in tex
|
assert "\\hlw{аппаратно}\\hlw{-}\\allowbreak \\hlw{программный}" in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_mark_in_figure_caption() -> None:
|
||||||
|
tex = render("![[images/a.png]]\n\nРисунок 1 — ==Схема== комплекса\n")
|
||||||
|
assert "\\caption{\\hlw{Схема} комплекса}" in tex
|
||||||
|
|
||||||
|
|
||||||
def test_mark_in_heading_reaches_the_contents() -> None:
|
def test_mark_in_heading_reaches_the_contents() -> None:
|
||||||
tex = render("## ==Контейнеризация серверного приложения==\n")
|
tex = render("## ==Контейнеризация серверного приложения==\n")
|
||||||
assert "\\subsection{\\hlw{Контейнеризация}" in tex
|
assert "\\subsection{\\hlw{Контейнеризация}" in tex
|
||||||
@@ -497,13 +502,20 @@ def test_abbreviation_dash_is_single() -> None:
|
|||||||
"""Шесть дефисов дают в LaTeX два длинных тире подряд вместо одного."""
|
"""Шесть дефисов дают в LaTeX два длинных тире подряд вместо одного."""
|
||||||
tex = body(render(ABBR_MD))
|
tex = body(render(ABBR_MD))
|
||||||
assert "------" not in tex
|
assert "------" not in tex
|
||||||
assert "--- Software-Defined Radio" in tex
|
assert "SDR & Software-Defined Radio" in tex
|
||||||
|
|
||||||
|
|
||||||
def test_abbreviation_table_has_no_extra_column_padding() -> None:
|
def test_abbreviation_table_has_no_extra_column_padding() -> None:
|
||||||
"""Отбивка между колонками добавляется к \\linewidth и роняет строку за поле."""
|
"""Отбивка между колонками добавляется к \\linewidth и роняет строку за поле."""
|
||||||
tex = body(render(ABBR_MD))
|
tex = body(render(ABBR_MD))
|
||||||
assert "@{}p{\\dimexpr\\linewidth" in tex
|
assert "{@{}l@{\\ ---\\ }X@{}}" in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_abbreviation_column_is_as_wide_as_the_abbreviation() -> None:
|
||||||
|
"""Колонка l берёт ширину по содержимому: до тире остаётся пробел."""
|
||||||
|
tex = body(render(ABBR_MD))
|
||||||
|
assert "p{" not in tex
|
||||||
|
assert "\\begin{tabularx}{\\linewidth}" in tex
|
||||||
|
|
||||||
|
|
||||||
def test_cpp_uses_extended_dialect() -> None:
|
def test_cpp_uses_extended_dialect() -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user