)]}'
{
  "commit": "f5ddf986bf5a6074ffcdb37a05d0760c1878cbfe",
  "tree": "396549bf5459351cb4fbab1e9f582e4e0e52563b",
  "parents": [
    "767a0995d3e450f312a2665ebfcc327b727c02cb"
  ],
  "author": {
    "name": "Andrew Chen",
    "email": "chuenchen309@gmail.com",
    "time": "Tue Sep 08 20:49:33 2026 +0800"
  },
  "committer": {
    "name": "Copybara-Service",
    "email": "copybara-worker@google.com",
    "time": "Wed Sep 09 05:31:38 2026 -0700"
  },
  "message": "🐛 FIX: render hardbreak and inline HTML in image alt text (#409)\n\n`RendererHTML.renderInlineAsText` builds the `alt` attribute for images\nby walking the inline token stream, but it only handles `text`, `image`\nand `softbreak` tokens. `hardbreak`, `html_inline` and `html_block` are\nsilently dropped, so a hard line break or inline HTML inside an image\ndescription disappears from the alt text.\n\n```python\nfrom markdown_it import MarkdownIt\nmd \u003d MarkdownIt(\"commonmark\")\n\nmd.render(\"![foo\\\\\\nbar](/url)\")   # hard break (backslash)\n# now:  \u003cp\u003e\u003cimg src\u003d\"/url\" alt\u003d\"foobar\" /\u003e\u003c/p\u003e\n# want: \u003cp\u003e\u003cimg src\u003d\"/url\" alt\u003d\"foo\\nbar\" /\u003e\u003c/p\u003e   (soft break already does this)\n\nmd.render(\"![a\u003cb\u003ec](/url)\")        # inline HTML\n# now:  \u003cp\u003e\u003cimg src\u003d\"/url\" alt\u003d\"ac\" /\u003e\u003c/p\u003e\n# want: \u003cp\u003e\u003cimg src\u003d\"/url\" alt\u003d\"a\u0026lt;b\u0026gt;c\" /\u003e\u003c/p\u003e\n```\n\n### Why this is the intended behaviour\n\nTwo independent references, both pointing the same way:\n\n- **JS parity.** This project is a port of `markdown-it` and the\nchangelog pins the parser to `markdown-it v14.1.0`. Upstream\n`renderInlineAsText` at that version handles `text`, `image`,\n`html_inline`, `html_block`, `softbreak` **and** `hardbreak`. The Python\nport is behind its own declared target for the last three.\n- **Internal consistency.** `softbreak` and `hardbreak` are treated as\nan identical pair everywhere else in the codebase; #157 previously added\nthe `softbreak` branch to this very function but stopped there. This\nchange is the sibling of that fix.\n\nHTML content in `alt` is escaped downstream by `renderAttrs` →\n`escapeHtml` (so `\u003cb\u003e` becomes `\u0026lt;b\u0026gt;`), matching the JS behaviour —\nno markup reaches the attribute unescaped.\n\n### The fix\n\nTwo grouped branches added to `renderInlineAsText`, making it a 1:1\nmatch of the upstream reference:\n\n```python\nelif token.type in (\"html_inline\", \"html_block\"):\n    result +\u003d token.content\nelif token.type in (\"softbreak\", \"hardbreak\"):\n    result +\u003d \"\\n\"\n```\n\n### Verification\n\n- Added two cases to `tests/test_port/fixtures/commonmark_extras.md`\n(hard break and inline HTML in an image description), mirroring the\nexisting #157 soft-break fixture. Both **fail without the change** and\n**pass with it**.\n- `renderInlineAsText` has a single production caller (the `image`\nrenderer), and the soft-break / plain-text paths are unchanged (verified\nas controls).\n- Full test suite: **983 passed**. `pre-commit` ruff, ruff-format and\nmypy (strict) all clean.\n\n---\n\nThis PR was authored by an AI coding agent (Claude Code) running on this\naccount: the AI found the bug, ran the repro, wrote the tests, and wrote\nthis description. The human account holder reviews every change and is\naccountable for it. The verification above is real and re-runnable from\nthe diff. If this isn\u0027t the kind of contribution you want, say so and\nI\u0027ll close it.\n\nSigned-off-by: chuenchen309 \u003c48723787+chuenchen309@users.noreply.github.com\u003e\nCo-authored-by: Chris Sewell \u003cchrisj_sewell@hotmail.com\u003e\nGitOrigin-RevId: 8501cf3369dc879353c5e5a2280941f73c42d392\nChange-Id: Ifca14f1ecc8e9c02e24e8c52f69f60d3599074a4\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "f690b091e2b16d249ab2d57f90cb2bb2276bbf66",
      "old_mode": 33188,
      "old_path": "markdown_it/renderer.py",
      "new_id": "73dbde1587f819c3648c622316adaa55908cf905",
      "new_mode": 33188,
      "new_path": "markdown_it/renderer.py"
    }
  ]
}
