diff --git a/src/md/html_renderer.rs b/src/md/html_renderer.rs index 45271496b521..6f1676d04a50 100644 --- a/src/md/html_renderer.rs +++ b/src/md/html_renderer.rs @@ -371,7 +371,10 @@ impl<'src> HtmlRenderer<'src> { } } TextType::Html => { - if self.tag_filter { + // Inside an image this is the value of `alt`, which a raw `"` would end. + if in_image { + self.write_html_escaped(content); + } else if self.tag_filter { self.write_html_with_tag_filter(content); } else { self.write(content); diff --git a/test/js/bun/md/md-edge-cases.test.ts b/test/js/bun/md/md-edge-cases.test.ts index e0c247cf5b11..e46d3ad373ba 100644 --- a/test/js/bun/md/md-edge-cases.test.ts +++ b/test/js/bun/md/md-edge-cases.test.ts @@ -953,6 +953,76 @@ describe("pathological inline HTML inputs", () => { }); }); +// The description of an image is the value of `alt`: a raw tag that is written there as it is +// ends the attribute at its first `"`. md4c: https://github.com/mity/md4c/pull/376 +describe("raw HTML in the description of an image", () => { + const image = (alt: string) => `

${alt}

\n`; + + test.each([ + // Every kind of raw HTML. + ['![x y z](i.png)', "x <a href="u">y</a> z"], + ['![](i.png)', "<a title="x" onerror="alert(1)">"], + ['![a e](i.png)', "a <b\nc="d"> e"], + ['![a b](i.png)', "a <i c="&amp;"> b"], + ['![a b](i.png)', "a <!-- "q" --> b"], + ['![a b](i.png)', "a <?php "q" ?> b"], + ['![a b](i.png)', "a <![CDATA[ "q" ]]> b"], + ['![a b](i.png)', "a <!DOCTYPE "q"> b"], + // An apostrophe stays: the attribute is in double quotes. + ["![a b](i.png)", "a <i c='d'> b"], + // A tag that the tag filter knows. + [ + '![