You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
✨ Add gfm-like2 preset with task lists, alerts, and single-tilde strikethrough (#388)
### Summary
Adds a new `gfm-like2` preset that extends `gfm-like` with three GFM
features:
- **Task lists** — `- [x] done` / `- [ ] todo` checkbox syntax in list
items
- **Alerts** — `> [!NOTE]`, `> [!TIP]`, `> [!WARNING]`, etc. inside
blockquotes
- **Single-tilde strikethrough** — `~text~` in addition to `~~text~~`
These are enabled via the `gfm-like2` preset or individually through the
`tasklists`, `alerts`, and `strikethrough_single_tilde` options. The
existing `gfm-like` preset is unchanged, so as to remain
back-compatible.
### Why in markdown-it-py, not mdit-py-plugins?
Task lists and alerts are implemented by integrating detection directly
into the existing block-level parsers (list.py and blockquote.py),
rather than as post-processing rules:
- Checkbox detection happens during list item parsing, before the
sub-parser runs on the item content
- Alert detection happens during blockquote parsing, before the inner
content is tokenized
This design is not achievable from a plugin: plugins can only add new
rules or post-process the token stream — they cannot modify the
internals of `list_block()` or `blockquote()` to inject detection at the
right point in the parsing pipeline. Implementing these as
post-processing core rules would work functionally, but it means
re-walking and mutating the token stream after the fact, which is less
clean and less consistent with how the block parsers are designed to
work.
Single-tilde strikethrough similarly extends the existing strikethrough
rule's matching logic (opener/closer width matching), which is more
naturally done inside the rule than bolted on externally.
### Changes
- **`rules_block/list.py`** — Detect `[ ]`/`[x]`/`[X]` at content start
during list item parsing; set `token.meta["checked"]`; advance `bMarks`
past the checkbox; add CSS classes (`task-list-item`,
`contains-task-list`) after the list loop
- **`rules_block/blockquote.py`** — Detect `[!TYPE]` on the first
content line; emit `alert_open`/`alert_close` + title tokens instead of
`blockquote_open`/`blockquote_close`; skip the marker line during
tokenization
- **`rules_inline/strikethrough.py`** — When
`strikethrough_single_tilde` is enabled, accept 1 or 2 tildes (reject
3+); enforce opener/closer width matching in `_postProcess`
- **renderer.py** — Add `list_item_open` render method that injects
checkbox HTML when `meta["checked"]` is present
- **`presets/__init__.py`** — Add `gfm_like2` preset class
- **`main.py`** — Register `gfm-like2` in `_PRESETS`
- **utils.py** — Add `tasklists`, `alerts`, `strikethrough_single_tilde`
keys to `OptionsType`
- **pyproject.toml** — Add `pytest-timeout` to test deps; set 10s
default timeout
- **Test fixtures** — 11 tasklist cases, 15 alert cases, 13 single-tilde
strikethrough cases
### Usage
```python
from markdown_it import MarkdownIt
md = MarkdownIt("gfm-like2")
md.render("- [x] done\n- [ ] todo")
md.render("> [!NOTE]\n> This is a note.")
md.render("~strikethrough~")
```
0 commit comments