diff options
Diffstat (limited to 'src/mistune/plugins/task_lists.py')
-rw-r--r-- | src/mistune/plugins/task_lists.py | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/mistune/plugins/task_lists.py b/src/mistune/plugins/task_lists.py new file mode 100644 index 0000000..8571c32 --- /dev/null +++ b/src/mistune/plugins/task_lists.py @@ -0,0 +1,67 @@ +import re + +__all__ = ['task_lists'] + + +TASK_LIST_ITEM = re.compile(r'^(\[[ xX]\])\s+') + + +def task_lists_hook(md, state): + return _rewrite_all_list_items(state.tokens) + + +def render_task_list_item(renderer, text, checked=False): + checkbox = ( + '<input class="task-list-item-checkbox" ' + 'type="checkbox" disabled' + ) + if checked: + checkbox += ' checked/>' + else: + checkbox += '/>' + + if text.startswith('<p>'): + text = text.replace('<p>', '<p>' + checkbox, 1) + else: + text = checkbox + text + + return '<li class="task-list-item">' + text + '</li>\n' + + +def task_lists(md): + """A mistune plugin to support task lists. Spec defined by + GitHub flavored Markdown and commonly used by many parsers: + + .. code-block:: text + + - [ ] unchecked task + - [x] checked task + + :param md: Markdown instance + """ + md.before_render_hooks.append(task_lists_hook) + if md.renderer and md.renderer.NAME == 'html': + md.renderer.register('task_list_item', render_task_list_item) + + +def _rewrite_all_list_items(tokens): + for tok in tokens: + if tok['type'] == 'list_item': + _rewrite_list_item(tok) + if 'children' in tok: + _rewrite_all_list_items(tok['children']) + return tokens + + +def _rewrite_list_item(tok): + children = tok['children'] + if children: + first_child = children[0] + text = first_child.get('text', '') + m = TASK_LIST_ITEM.match(text) + if m: + mark = m.group(1) + first_child['text'] = text[m.end():] + + tok['type'] = 'task_list_item' + tok['attrs'] = {'checked': mark != '[ ]'} |