Preserve strikethrough from <strike> and CSS line-through (#2342)

* Keep strikethrough for <strike> and CSS line-through.

<s> and <del> already became ~~text~~. The obsolete strike element and inline text-decoration: line-through were flattened to plain text, so deleted wording looked current.

* Don't handle css style tags yet.

---------

Co-authored-by: afourney <adamfo@microsoft.com>
This commit is contained in:
Gyanu Mayank
2026-09-01 16:20:29 -07:00
committed by GitHub
co-authored by afourney
parent d04418ec9a
commit be631e1fc0
2 changed files with 42 additions and 0 deletions
@@ -122,5 +122,9 @@ class _CustomMarkdownify(markdownify.MarkdownConverter):
return "[x] " if el.has_attr("checked") else "[ ] "
return ""
def convert_strike(self, el: Any, text: str, *args, **kwargs) -> str:
"""Obsolete <strike> is still in the wild; treat it like <s>/<del>."""
return self.convert_s(el, text, *args, **kwargs) # type: ignore
def convert_soup(self, soup: Any) -> str:
return super().convert_soup(soup) # type: ignore
@@ -264,6 +264,44 @@ def test_docx_comments() -> None:
validate_strings(result, DOCX_COMMENT_TEST_STRINGS)
def test_html_strikethrough_variants(tmp_path) -> None:
html = """<!doctype html>
<html><body>
<p>Plain <s>s element</s> after.</p>
<p>Plain <del>del element</del> after.</p>
<p>Plain <strike>strike element</strike> after.</p>
<p>Spaces A<strike> B </strike>C.</p>
<p>Runs D<strike> E </strike>F.</p>
<p>Empty G<strike></strike>H.</p>
<p>Newline I<strike>J
K</strike>L.</p>
<p>Break M<strike>N<br>O</strike>P.</p>
</body></html>
"""
path = tmp_path / "strike.html"
path.write_text(html, encoding="utf-8")
markdown = MarkItDown().convert(str(path)).markdown
assert markdown == "\n\n".join(
[
# <s>, <del> and the obsolete <strike> all mean strikethrough
"Plain ~~s element~~ after.",
"Plain ~~del element~~ after.",
"Plain ~~strike element~~ after.",
# Surrounding whitespace stays outside of the markup ...
"Spaces A ~~B~~ C.",
# ... and runs of it collapse to a single space
"Runs D ~~E~~ F.",
# An empty element contributes nothing
"Empty GH.",
# A line break inside the element is kept, and the markup
# survives it because strikethrough may span a single newline
"Newline I~~J\nK~~L.",
"Break M~~N\nO~~P.",
]
)
def test_docx_equations() -> None:
markitdown = MarkItDown()
docx_file = os.path.join(TEST_FILES_DIR, "equations.docx")