Add support for gfm task lists
KristopherGBaker opened this issue · 3 comments
Task lists are now supported in libcmark-gfm, add the support to Maaku.
I've got a chunk of this done. I've got a question as to what might be a better approach.
One approach is to have Lists contain ListItems as now, and include a TaskList item as the first item in the ListItem's block that captures the info of whether the task is completed. This would lead to a tree kind of like:
List
ListItem
TaskList
Paragraph
ListItem
TaskList
Paragraph
With this style, the only thing a LIst will contain directly are ListItem objects. A Tasklist only captures the state of whether the task was complete or not. The text of the task is captured as other parts of the ListItem. This is somewhat analogous to how the HTML is generated: the task adds an input (<input type="checkbox" checked="" disabled="" />
for example) between the <li>
and the text of the list item.
Another approach is to have the TaskList item itself contain the text of the task. This would lead to a tree like:
List
ListItem
TaskList
Paragraph
ListItem
TaskList
Paragraph
I like this approach, because TaskList.attributedString
could make the task text look different depending on whether the task was completed (e.g. use strikethrough so it's obvious that the task is completed). [If you like the first approach (TaskList is just one item among many under the LIstItem), there could be a function on TaskList that takes an array of items and creates an appropriate attributed string on them based on the completion status, allowing the user a way to get the task completion status to affect the attributes of the text of the task].
A different approach is to have TaskItem be roughly equivalent with ListItem -- so a List would be composed of any combination of ListItem or TaskItem pieces. This is somewhat equivalent to what the rendered XML is. However, that means when processing a List, you have potentially two different types of objects in it. The approaches above have the benefit of Lists only having one type of object in them.
I can give you CMark with tasklist extensions right now, and could give you whichever of the three approaches above pretty quickly (I first tried the first then switched to the second when playing around).
For comparison, the following CommonMark:
- [ ] task 1
- [x] completed ~~task~~
- [X] another completed task
- not a task
generates this HTML (note list only contains <li>
items):
<ul>
<li><input type="checkbox" disabled="" /> task 1</li>
<li><input type="checkbox" checked="" disabled="" /> completed ~~task~~</li>
<li><input type="checkbox" checked="" disabled="" /> another completed task</li>
<li>not a task</li>
</ul>
and this XML (note list contains both <tasklist>
and <item>
):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document SYSTEM "CommonMark.dtd">
<document xmlns="http://commonmark.org/xml/1.0">
<list type="bullet" tight="true">
<tasklist completed="false">
<paragraph>
<text xml:space="preserve">task 1</text>
</paragraph>
</tasklist>
<tasklist completed="true">
<paragraph>
<text xml:space="preserve">completed ~~task~~</text>
</paragraph>
</tasklist>
<tasklist completed="true">
<paragraph>
<text xml:space="preserve">another completed task</text>
</paragraph>
</tasklist>
<item>
<paragraph>
<text xml:space="preserve">not a task</text>
</paragraph>
</item>
</list>
</document>
This XML was generated with changes I made to the tasklist extension and have issued a pull request for to the cmark-gfm repository and includes the completion state of the task in the element. The standard library just has the tasklist
tag, but no info about completion state
I prefer the second or third approach. For the third approach, do you think it would work if ListItem
and TaskItem
shared a common Item
protocol, and then when processing a list you would only generally care about using the protocol? You're more familiar with task lists, so I'll trust your judgement on which approach to take. Thanks for all of your work on this.
I like your idea of doing the third approach, but with an Item
protocol that both ListItem
and TaskItem
support. Let me play with this for a day or so to see how it all works out. I do think that making the XML version be a kind of "standard" might make future design decisions easier.