Skip to content

Honor the value attribute on <li> in ordered lists#263

Open
gaoflow wants to merge 1 commit into
matthewwithanm:developfrom
gaoflow:fix-li-value-ordinal
Open

Honor the value attribute on <li> in ordered lists#263
gaoflow wants to merge 1 commit into
matthewwithanm:developfrom
gaoflow:fix-li-value-ordinal

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 20, 2026

Copy link
Copy Markdown

Summary

markdownify numbers <ol> items purely by position, so an explicit value attribute on an <li> is silently ignored and the converted Markdown renders different numbering than the source HTML:

>>> from markdownify import markdownify as md
>>> md('<ol><li>a</li><li value="5">b</li><li>c</li></ol>')
'\n\n1. a\n2. b\n3. c\n'    # expected '1. a', '5. b', '6. c'

Per the HTML spec, value sets that item's ordinal and the following items continue counting from it. The library already honors <ol start>, but never read <li value>.

Fix

In convert_li, before falling back to the positional number, walk from the current item backwards (nearest first, including the item itself) for the closest numeric value; the ordinal is int(value) + offset, where offset is the number of items between it and the current one. Non-numeric or negative value falls back to positional numbering, mirroring the existing start guard (.isnumeric()).

number = start + len(el.find_previous_siblings('li'))
for offset, li in enumerate([el] + el.find_previous_siblings('li')):
    value = li.get("value")
    if value and str(value).isnumeric():
        number = int(value) + offset
        break
bullet = '%s.' % number

This composes correctly with <ol start> and with multiple value attributes:

HTML before after
<ol><li>a<li value="5">b<li>c 1, 2, 3 1, 5, 6
<ol start="2"><li>a<li value="10">b<li value="4">c<li>d 2, 3, 4, 5 2, 10, 4, 5
<ol><li value="foo">a<li>b 1, 2 1, 2 (fallback)

Verification

  • Added 5 assertions to tests/test_lists.py::test_ol (the bug case, value-on-first-item, the compound start + multiple value case, and non-numeric/negative fallback). They fail before the fix and pass after.
  • Full suite: 83 passed. flake8 --ignore=E501,W503 markdownify tests clean.

This pull request was prepared with the assistance of AI, under my direction and review.

markdownify numbered <ol> items purely by position, so an explicit
value attribute on an <li> was ignored. Per the HTML spec, value sets
that item's ordinal and the following items continue counting from it,
e.g. '<ol><li>a<li value="5">b<li>c' is 1, 5, 6 (not 1, 2, 3).

Walk from the item backwards for the nearest numeric value and offset
by the number of items that follow it. Non-numeric or negative values
fall back to positional numbering, mirroring the existing start guard.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant