from linkki_poster.formatting import ( CAPTION_LIMIT, estimate_caption_length, parse_markdown_template, render_preview_html, render_template, validate_markdown_syntax, ) from linkki_poster.models import Language def test_markdown_subset_and_placeholder_rendering() -> None: raw = ( "# title\n" "**bold** _italic_ ++under++ ~~strike~~ ||spoil|| `code` [site](https://example.com)\n" "Go [English](en) and [Finnish](fi)\n" ) parsed = parse_markdown_template(raw) unresolved = render_template(parsed, {}) assert "TITLE" in unresolved assert "bold" in unresolved assert "italic" in unresolved assert "under" in unresolved assert "strike" in unresolved assert "spoil" in unresolved assert "code" in unresolved assert 'site' in unresolved assert "English" in unresolved assert "Finnish" in unresolved assert 'href="https://t.me/' not in unresolved resolved = render_template( parsed, { Language.EN: "https://t.me/testchan/123", Language.FI: "https://t.me/testchan/456", }, ) assert 'English' in resolved assert 'Finnish' in resolved def test_caption_length_estimate_uses_worst_case_links() -> None: parsed = parse_markdown_template("[EN](en) " * 80) assert estimate_caption_length(parsed, "channel") > CAPTION_LIMIT def test_multiline_spoiler_is_supported() -> None: parsed = parse_markdown_template("||line1\n\nline2||") rendered = render_template(parsed, {}) assert "line1\n\nline2" in rendered def test_validate_markdown_syntax_finds_unclosed_markers() -> None: issues = validate_markdown_syntax("Can we do **[bold links](fi)") messages = [issue.message for issue in issues] assert any("**" in message for message in messages) def test_lists_and_blockquotes_are_rendered_for_telegram_html() -> None: parsed = parse_markdown_template( "- item\n" " - nested\n" "1. first\n" " 1. nested first\n" "> quoted\n" "> text\n" ) rendered = render_template(parsed, {}) assert "• item" in rendered assert "\u00a0\u00a0\u00a0\u00a0• nested" in rendered assert "1. first" in rendered assert "\u00a0\u00a0\u00a0\u00a01. nested first" in rendered assert "
quoted\ntext
" in rendered def test_escaped_list_markers_and_heading_markers_stay_literal() -> None: parsed = parse_markdown_template("\\* not a list\n1\\. not numbered\n\\# not a heading") rendered = render_template(parsed, {}) assert "* not a list" in rendered assert "1. not numbered" in rendered assert "# not a heading" in rendered def test_escaped_backticks_and_link_brackets_stay_literal() -> None: parsed = parse_markdown_template( r"test \`code` test" "\n" r"\```" "\n" "code\n" "```\n" r"\[label\]\(url\)" ) rendered = render_template(parsed, {}) assert r"test `code` test" in rendered assert "code" not in rendered assert "
" not in rendered
    assert "[label](url)" in rendered


def test_escaped_cross_language_link_stays_literal() -> None:
    parsed = parse_markdown_template(r"\[English](en)")
    rendered = render_template(parsed, {Language.EN: "https://t.me/test/123"})
    assert "[English](en)" in rendered
    assert 'href="https://t.me/test/123"' not in rendered


def test_preview_renders_fake_links_for_available_targets() -> None:
    preview = render_preview_html("[English](en) [Finnish](fi)", {Language.EN})
    assert 'English' in preview
    assert "Finnish" in preview
    assert 'href="#fi"' not in preview


def test_apostrophes_are_not_escaped_in_headings_or_plain_text() -> None:
    heading = render_template(parse_markdown_template("#THERE'S"), {})
    plain_heading_char = render_template(parse_markdown_template("#'"), {})
    bold = render_template(parse_markdown_template("**THERE'S**"), {})

    assert "THERE'S" in heading
    assert "'" in plain_heading_char
    assert "THERE'S" in bold
    assert "'" not in heading
    assert "'" not in plain_heading_char
    assert "'" not in bold