Problem
simplifyHtml keeps <b>, <i>, <s> and <strike> as raw HTML in the Markdown output, while their siblings <strong>, <em> and <del> become **…**, *…* and ~~…~~:
<p><b>bold</b> <strong>strong</strong> <i>it</i> <em>em</em> <s>gone</s></p>
renders as
<b>bold</b> **strong** <i>it</i> *em* <s>gone</s>
It shows up on real pages: the Hacker News dump fixture (markanywhere-html/src/commonTest/kotlin/dumps/HackerNewsTest.kt) has <b>[Hacker News](ref:2:news)</b> on its first line.
Current rationale
This is deliberate. b/i/s/strike are absent from MARKDOWN_NATIVE_TAGS (SimplifyHtml.kt), and the behaviour is pinned by SimplifyHtmlTest › "should preserve b i and s and strike tags as they are", whose comment gives the reason:
<b>, <i>, <s> elements were rescued from being "italic/bold" buttons into semantic roles, <strike> is depreciated, but we might still see it in the content
That refers to HTML5 giving these tags meanings of their own: <b> draws attention without implying importance, <i> marks idiomatic text or another voice, and <s> marks content that is no longer accurate. So writing them as **/*/~~ would turn them into <strong>/<em>/<del> if the Markdown were converted back to HTML. It came in with the original pipeline (#53) and nothing else argues for it.
Why reverse it
- The main consumers read the Markdown; they don't convert it back to HTML. For an LLM or a human reader,
**x** means "shown in bold". The difference between "draws attention" and "important" doesn't reach that reader either way, and they can't act on it.
- The web doesn't follow the HTML5 meanings. Older sites, forums and plenty of CMS output use
<b>/<i> simply for bold and italic. Wikipedia, for example, puts the article's subject in <b> and titles in <i>.
- Raw tags are noise in a format meant to drop markup. They cost tokens, and a consumer that expects Markdown ends up handling stray HTML in ordinary text.
- Little is lost. The only casualty is exact round-tripping from Markdown back to the original tag names, which no consumer relies on.
Proposed change
In simplifyHtml, rename the elements and emit them untagged, so the renderer writes native Markdown:
| HTML |
becomes |
Markdown |
<b> |
strong |
**…** |
<i> |
em |
*…* |
<s>, <strike> |
del |
~~…~~ |
Keep <u> (and the rest of INLINE_FORMATTING_TAGS without a Markdown equivalent) as raw HTML, since Markdown has no underline.
Things to check:
- Nesting and adjacency. For example
<b><strong>x</strong></b>, <b>a</b><b>b</b>, <i> inside <em>, and emphasis in the middle of a word (foo<b>bar</b>baz). The existing delimiter-escaping logic (see EmphasisDelimiterRoundTripTest) must still produce Markdown that re-parses to the same structure, without growing on each round trip. Collapsing a redundant strong inside a strong is optional.
- Empty icon elements such as
<i class="fa-solid fa-sun"></i> must not become a bare **/*. dropBlankInlineFormatting should still remove them; add a test, since the element now goes through a renamed path.
HtmlToMarkdownTest already has an icon <i> fixture; keep it passing.
- Don't touch the parser. A literal
<b> written in Markdown source should still parse as a tagged b (see MarkanywhereParserTest, TransformationTest and the README examples). This change only affects the HTML → Markdown direction.
Tests to update
SimplifyHtmlTest › "should preserve b i and s and strike tags as they are": rewrite it to assert the mapping above, and give it a matching name.
HackerNewsTest: its first line should become **[Hacker News](ref:2:news)**.
- Add a round-trip case to
EmphasisDelimiterRoundTripTest for <b> containing a literal *.
- Mention the behaviour change in the CHANGELOG/README if those describe
simplifyHtml's tag handling.
Problem
simplifyHtmlkeeps<b>,<i>,<s>and<strike>as raw HTML in the Markdown output, while their siblings<strong>,<em>and<del>become**…**,*…*and~~…~~:renders as
It shows up on real pages: the Hacker News dump fixture (
markanywhere-html/src/commonTest/kotlin/dumps/HackerNewsTest.kt) has<b>[Hacker News](ref:2:news)</b>on its first line.Current rationale
This is deliberate.
b/i/s/strikeare absent fromMARKDOWN_NATIVE_TAGS(SimplifyHtml.kt), and the behaviour is pinned bySimplifyHtmlTest› "should preserve b i and s and strike tags as they are", whose comment gives the reason:That refers to HTML5 giving these tags meanings of their own:
<b>draws attention without implying importance,<i>marks idiomatic text or another voice, and<s>marks content that is no longer accurate. So writing them as**/*/~~would turn them into<strong>/<em>/<del>if the Markdown were converted back to HTML. It came in with the original pipeline (#53) and nothing else argues for it.Why reverse it
**x**means "shown in bold". The difference between "draws attention" and "important" doesn't reach that reader either way, and they can't act on it.<b>/<i>simply for bold and italic. Wikipedia, for example, puts the article's subject in<b>and titles in<i>.Proposed change
In
simplifyHtml, rename the elements and emit them untagged, so the renderer writes native Markdown:<b>strong**…**<i>em*…*<s>,<strike>del~~…~~Keep
<u>(and the rest ofINLINE_FORMATTING_TAGSwithout a Markdown equivalent) as raw HTML, since Markdown has no underline.Things to check:
<b><strong>x</strong></b>,<b>a</b><b>b</b>,<i>inside<em>, and emphasis in the middle of a word (foo<b>bar</b>baz). The existing delimiter-escaping logic (seeEmphasisDelimiterRoundTripTest) must still produce Markdown that re-parses to the same structure, without growing on each round trip. Collapsing a redundantstronginside astrongis optional.<i class="fa-solid fa-sun"></i>must not become a bare**/*.dropBlankInlineFormattingshould still remove them; add a test, since the element now goes through a renamed path.HtmlToMarkdownTestalready has an icon<i>fixture; keep it passing.<b>written in Markdown source should still parse as a taggedb(seeMarkanywhereParserTest,TransformationTestand the README examples). This change only affects the HTML → Markdown direction.Tests to update
SimplifyHtmlTest› "should preserve b i and s and strike tags as they are": rewrite it to assert the mapping above, and give it a matching name.HackerNewsTest: its first line should become**[Hacker News](ref:2:news)**.EmphasisDelimiterRoundTripTestfor<b>containing a literal*.simplifyHtml's tag handling.