[ADD] пометка правок ==текст== жёлтым выделением
Рецензент просит показывать в отчёте только исправленные места, чтобы не перечитывать текст целиком. Разметка разбирается на уровне текстовых узлов, поэтому «==» в листингах на C++ остаётся сравнением. Выделяется каждое слово отдельно: одной плашкой на всё выделение строка не разорвётся по его середине, а выделять приходится и целые предложения. Составное слово делится по дефису — плашка неразрывна, и шорткат переноса внутри неё не работает. soul не подошёл: под XeLaTeX его \hl теряет кириллицу.
This commit is contained in:
@@ -51,6 +51,7 @@ docker build -t md2gost .
|
|||||||
- Изображения (см. ниже)
|
- Изображения (см. ниже)
|
||||||
- Аббревиатуры (раздел "Перечень принятых сокращений")
|
- Аббревиатуры (раздел "Перечень принятых сокращений")
|
||||||
- Ссылки, жирный, курсив
|
- Ссылки, жирный, курсив
|
||||||
|
- Пометка правок `==текст==` — жёлтое выделение для рецензента
|
||||||
|
|
||||||
### Изображения
|
### Изображения
|
||||||
|
|
||||||
|
|||||||
@@ -81,9 +81,49 @@ def bind_initials(text: str) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
# ==текст== — пометка правки для рецензента. Разметки такого рода в
|
||||||
|
# CommonMark нет, поэтому она разбирается здесь, на уровне текстовых узлов:
|
||||||
|
# внутрь листингов и инлайн-кода регулярное выражение не попадает, и «==»
|
||||||
|
# в исходниках на C++ остаётся сравнением. Границы выделения примыкают к
|
||||||
|
# тексту вплотную — как у прочих парных знаков разметки.
|
||||||
|
_MARK_RE = re.compile(r"==(?=\S)(.+?)(?<=\S)==")
|
||||||
|
|
||||||
|
|
||||||
|
def render_text(text: str) -> str:
|
||||||
|
return split_compounds(bind_initials(escape_latex(text)))
|
||||||
|
|
||||||
|
|
||||||
|
def highlight_word(word: str) -> str:
|
||||||
|
"""Слово в жёлтой плашке, составное — по плашке на каждую часть.
|
||||||
|
|
||||||
|
Плашка неразрывна, поэтому шорткат переноса «"=» внутри неё не работает
|
||||||
|
и «аппаратно-программный» целиком вылезает за поле. Дефис получает свою
|
||||||
|
плашку, а точка переноса ставится после неё.
|
||||||
|
"""
|
||||||
|
parts = [part for part in word.split("-") if part]
|
||||||
|
return "\\hlw{-}\\allowbreak ".join(f"\\hlw{{{part}}}" for part in parts)
|
||||||
|
|
||||||
|
|
||||||
|
def highlight(text: str) -> str:
|
||||||
|
"""Жёлтая плашка на каждом слове.
|
||||||
|
|
||||||
|
Одной плашкой на всё выделение строка не разорвётся по его середине,
|
||||||
|
а выделять приходится и целые предложения.
|
||||||
|
"""
|
||||||
|
escaped = bind_initials(escape_latex(text))
|
||||||
|
return " ".join(highlight_word(word) for word in escaped.split(" ") if word)
|
||||||
|
|
||||||
|
|
||||||
@inline("text")
|
@inline("text")
|
||||||
def _text(tok: Token) -> str:
|
def _text(tok: Token) -> str:
|
||||||
return split_compounds(bind_initials(escape_latex(tok.content)))
|
parts: list[str] = []
|
||||||
|
end = 0
|
||||||
|
for match in _MARK_RE.finditer(tok.content):
|
||||||
|
parts.append(render_text(tok.content[end : match.start()]))
|
||||||
|
parts.append(highlight(match.group(1)))
|
||||||
|
end = match.end()
|
||||||
|
parts.append(render_text(tok.content[end:]))
|
||||||
|
return "".join(parts)
|
||||||
|
|
||||||
|
|
||||||
@inline("strong_open")
|
@inline("strong_open")
|
||||||
|
|||||||
@@ -37,6 +37,30 @@ def test_unnumbered_heading() -> None:
|
|||||||
assert "ВВЕДЕНИЕ" in tex
|
assert "ВВЕДЕНИЕ" in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_mark_highlights_every_word() -> None:
|
||||||
|
tex = render("Обычный ==правленый текст== дальше.\n")
|
||||||
|
assert "\\hlw{правленый} \\hlw{текст}" in tex
|
||||||
|
assert "Обычный " in tex
|
||||||
|
assert " дальше." in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_mark_splits_compound_word_into_separate_boxes() -> None:
|
||||||
|
# Плашка неразрывна: составное слово одним боксом вылезает за поле.
|
||||||
|
tex = render("==аппаратно-программный комплекс==\n")
|
||||||
|
assert "\\hlw{аппаратно}\\hlw{-}\\allowbreak \\hlw{программный}" in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_mark_in_heading_reaches_the_contents() -> None:
|
||||||
|
tex = render("## ==Контейнеризация серверного приложения==\n")
|
||||||
|
assert "\\subsection{\\hlw{Контейнеризация}" in tex
|
||||||
|
|
||||||
|
|
||||||
|
def test_comparison_in_listing_is_not_a_mark() -> None:
|
||||||
|
tex = body(render("```cpp\nif (a==b && c==d) return;\n```\n"))
|
||||||
|
assert "\\hlw" not in tex
|
||||||
|
assert "a==b" in tex
|
||||||
|
|
||||||
|
|
||||||
def test_list_punctuation() -> None:
|
def test_list_punctuation() -> None:
|
||||||
tex = render("- один\n- два\n- три\n")
|
tex = render("- один\n- два\n- три\n")
|
||||||
assert " \\item один;" in tex
|
assert " \\item один;" in tex
|
||||||
|
|||||||
Reference in New Issue
Block a user