Skip to content

Fix tasklist: find the marker inside containers, take the checked state from the marker - #396

Open
itayavtalyon wants to merge 1 commit into
github:masterfrom
itayavtalyon:fix/tasklist-marker-cmark-gfm
Open

itayavtalyon wants to merge 1 commit into
github:masterfrom
itayavtalyon:fix/tasklist-marker-cmark-gfm

Conversation

@itayavtalyon

Copy link
Copy Markdown

Two bugs in extensions/tasklist.c:

  1. checked comes from strstr(input, "[x]") || strstr(input, "[X]") over the rest of the line, so - [ ] buy [x] item renders as a checked task.
  2. scan_tasklist(input, len, 0) scans from the start of the raw line, so the container prefix defeats it: > - [ ] quoted (or a task list inside a block quote at any depth) is never a task item.

Fix

open_tasklist_item now:

  • checks the marker at the item's first non-space character (cmark_parser_get_first_nonspace), not at offset 0 of the line;
  • acts only on the line that opens the item (start_line == line_number), so [ ] at the start of a continuation line stays text, as before;
  • accepts after ] the same characters as the old scanner's spacechar class (space, tab, VT, FF), so - [ ] at the end of a line is still not a task, as before;
  • sets checked from that marker character only.

Tests

Seven new examples in test/regression.txt, tagged tasklist: the two bugs, a task list in a quote inside a list, and four examples that pin existing behaviour (a continuation line, a marker at line end, a marker on a later line, near-miss markers such as [x) and [y]).

A differential run of the unfixed and fixed cmark-gfm binaries (this branch and master) over every example in spec.txt, extensions.txt, regression.txt and smart_punct.txt, with all extensions enabled (751 examples), changes the output only for the new regression examples. A further 18 task edge forms (list padding, tabs, [], [ ]x, ordered markers, a marker on a later line) give identical output.

ctest: 13/13 pass.

The same fix is proposed to swiftlang/swift-cmark in swiftlang#103.

🤖 Generated with Claude Code

The tasklist extension scanned for the marker from the start of the raw
line, so a task list item inside a block quote (`> - [ ] task`) was never
recognised. It also set the checked state with strstr over the rest of
the line, so `- [ ] buy [x] item` rendered as checked.

Look for the marker at the item's first non-space character, only on the
line that opens the item, and take the checked state from that marker.
The characters allowed after the marker match the original scanner's
spacechar class (space, tab, VT, FF), so `- [ ]` at the end of a line is
still not a task.

Over every example in spec.txt, extensions.txt, regression.txt and
smart_punct.txt with all extensions on, only the new regression examples
change output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@itayavtalyon
itayavtalyon marked this pull request as ready for review October 27, 2026 15:36
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