Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/pymax/formatting/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,29 @@ def _parse_link(

return label, url, url_end + 1

@staticmethod
def _is_intraword_single_marker(text: str, i: int, marker: str) -> bool:
if marker not in {"_", "*"}:
return False
if i == 0 or i + 1 >= len(text):
return False
return text[i - 1].isalnum() and text[i + 1].isalnum()

@staticmethod
def _find_closing_marker(
text: str,
marker: str,
start: int,
end: int | None = None,
) -> int:
while True:
closing_index = text.find(marker, start, len(text) if end is None else end)
if closing_index == -1:
return -1
if not Formatter._is_intraword_single_marker(text, closing_index, marker):
return closing_index
start = closing_index + len(marker)

@staticmethod
def format_markdown(text: str) -> tuple[str, list[Element]]:
clean_text = ""
Expand Down Expand Up @@ -155,6 +178,8 @@ def format_markdown(text: str) -> tuple[str, list[Element]]:
for marker in Formatter.MARKER_ORDER:
if not text.startswith(marker, i):
continue
if Formatter._is_intraword_single_marker(text, i, marker):
continue
Comment thread
coderabbitai[bot] marked this conversation as resolved.

marker_len = len(marker)

Expand All @@ -180,7 +205,8 @@ def format_markdown(text: str) -> tuple[str, list[Element]]:
break

end = text.find("\n", i + marker_len)
closing_index = text.find(
closing_index = Formatter._find_closing_marker(
text,
marker,
i + marker_len,
None if end == -1 else end,
Expand Down
26 changes: 26 additions & 0 deletions tests/files/test_files_and_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,29 @@ def test_markdown_formatter_extracts_functional_entities() -> None:
]
assert entities[-1].attributes is not None
assert entities[-1].attributes.url == "https://example.com"


def test_markdown_formatter_preserves_intraword_single_markers() -> None:
text = "https://max.ru/channel_iclub_new snake_case_name цена 5*2 = 10"

clean, entities = Formatter.format_markdown(text)

assert clean == text
assert entities == []


def test_markdown_formatter_preserves_unclosed_single_marker_before_intraword_marker() -> None:
clean, entities = Formatter.format_markdown("_foo_bar")

assert clean == "_foo_bar"
assert entities == []


def test_markdown_formatter_still_parses_delimited_single_marker_emphasis() -> None:
clean, entities = Formatter.format_markdown("Hello _world_ and *again*")

assert clean == "Hello world and again"
assert [(entity.type, entity.from_, entity.length) for entity in entities] == [
("EMPHASIZED", 6, 5),
("EMPHASIZED", 16, 5),
]