Source code for atlas_doc_parser.nodes.node_task_list
# -*- coding: utf-8 -*-importtypingasTimportdataclassesfromfunc_args.apiimportREQ,OPTfrom..type_enumimportTypeEnumfrom..mark_or_nodeimportBase,BaseNodeifT.TYPE_CHECKING:# pragma: no coverfrom.node_task_itemimportNodeTaskItemfrom.node_block_task_itemimportNodeBlockTaskItem
[docs]@dataclasses.dataclass(frozen=True)classNodeTaskListAttrs(Base):""" Attributes for :class:`NodeTaskList`. :param localId: A unique identifier for the task list. """localId:str=REQ
[docs]@dataclasses.dataclass(frozen=True)classNodeTaskList(BaseNode):""" A container for task/checkbox items. The taskList node is a block node that groups multiple taskItem nodes together for rendering as a checklist. It can also contain nested taskList nodes for hierarchical task structures. """type:str=TypeEnum.taskList.valueattrs:NodeTaskListAttrs=REQcontent:list[T.Union["NodeTaskItem","NodeTaskList","NodeBlockTaskItem",]]=REQ
[docs]defto_markdown(self,level:int=0,ignore_error:bool=False,)->str:""" Convert the task list to Markdown format. **ADF Structure** (nested list is a **sibling** of taskItem):: taskList ├── taskItem (item 1) → [text nodes] ← text directly in content ├── taskList (nested) ← nested list is SIBLING of taskItem │ ├── taskItem (item 1.1) │ └── taskList (nested) │ └── taskItem (item 1.1.1) ├── taskItem (item 2) ├── taskList (nested) ... **Implementation**: Uses a single loop because: - ``taskItem`` and nested ``taskList`` are **siblings** in ``taskList.content`` - Text nodes are directly inside ``taskItem.content`` (no wrapper like paragraph) - The loop handles both ``taskItem`` (render with checkbox) and ``taskList`` (recursive call with increased level) in the same iteration .. note:: This structure differs from :meth:`~atlas_doc_parser.nodes.node_bullet_list.NodeBulletList.to_markdown` and :meth:`~atlas_doc_parser.nodes.node_ordered_list.NodeOrderedList.to_markdown` where nested lists are **children** of ``listItem`` nodes, requiring two nested loops. .. seealso:: - :meth:`~atlas_doc_parser.nodes.node_bullet_list.NodeBulletList.to_markdown` - different structure, two loops - :meth:`~atlas_doc_parser.nodes.node_ordered_list.NodeOrderedList.to_markdown` - different structure, two loops """lines=[]indent=" "*level# 4 spaces per levelforiteminself.content:ifitem.is_type_of(TypeEnum.taskItem):# Process the task item content (text nodes)content_parts=[]fornodeinitem.content:try:md=node.to_markdown()content_parts.append(md)exceptExceptionase:ifignore_error:passelse:raisee# Join content parts (they should be on the same line)# Use rstrip() on the final result to remove trailing whitespaceitem_content="".join(content_parts).rstrip()# Determine checkbox state based on item.attrs.statecheckbox="[x]"ifitem.attrs.state=="DONE"else"[ ]"# Format the line with checkboxline=f"{indent}- {checkbox}{item_content}"lines.append(line)elifitem.is_type_of(TypeEnum.taskList):# Nested task list - increase leveltry:md=item.to_markdown(level=level+1,ignore_error=ignore_error)lines.append(md)exceptExceptionase:ifignore_error:passelse:raiseereturn"\n".join(lines)