GFM Task Lists Example
This example demonstrates how to create GitHub Flavored Markdown task lists, which are essentially checkboxes that can be either checked or unchecked.
Basic Task List Example
rust
#[cfg(feature = "gfm")]
use cmark_writer::ast::{Node, ListItem, TaskListStatus};
use cmark_writer::options::WriterOptionsBuilder;
use cmark_writer::writer::CommonMarkWriter;
#[cfg(feature = "gfm")]
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a document with task lists
let document = Node::Document(vec![
Node::heading(1, vec![Node::Text("Project Tasks".to_string())]),
Node::Paragraph(vec![
Node::Text("The following tasks need to be completed:".to_string())
]),
// Unordered list with task items
Node::UnorderedList(vec![
// Unchecked task
ListItem::Task {
status: TaskListStatus::Unchecked,
content: vec![Node::Paragraph(vec![
Node::Text("Implement feature X".to_string())
])],
},
// Checked task
ListItem::Task {
status: TaskListStatus::Checked,
content: vec![Node::Paragraph(vec![
Node::Text("Write documentation".to_string())
])],
},
// Another unchecked task
ListItem::Task {
status: TaskListStatus::Unchecked,
content: vec![Node::Paragraph(vec![
Node::Text("Test on various platforms".to_string())
])],
},
// Nested tasks
ListItem::Task {
status: TaskListStatus::Unchecked,
content: vec![
Node::Paragraph(vec![Node::Text("Deploy to production".to_string())]),
// Nested task list
Node::UnorderedList(vec![
ListItem::Task {
status: TaskListStatus::Checked,
content: vec![Node::Paragraph(vec![
Node::Text("Prepare staging environment".to_string())
])],
},
ListItem::Task {
status: TaskListStatus::Unchecked,
content: vec![Node::Paragraph(vec![
Node::Text("Configure CI/CD pipeline".to_string())
])],
},
]),
],
},
]),
]);
// Configure writer with GFM task lists enabled
let options = WriterOptionsBuilder::new()
.gfm_tasklists(true)
.build();
let mut writer = CommonMarkWriter::with_options(options);
writer.write(&document)?;
let markdown = writer.into_string();
// Print the generated markdown
println!("{}", markdown);
Ok(())
}
#[cfg(not(feature = "gfm"))]
fn main() {
println!("This example requires the 'gfm' feature to be enabled");
}
With the gfm
feature enabled, this produces:
markdown
# Project Tasks
The following tasks need to be completed:
- [ ] Implement feature X
- [x] Write documentation
- [ ] Test on various platforms
- [ ] Deploy to production
- [x] Prepare staging environment
- [ ] Configure CI/CD pipeline
Mixed List Types Example
You can mix task list items with regular list items:
rust
#[cfg(feature = "gfm")]
use cmark_writer::ast::{Node, ListItem, TaskListStatus};
use cmark_writer::options::WriterOptionsBuilder;
use cmark_writer::writer::CommonMarkWriter;
#[cfg(feature = "gfm")]
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a document with mixed list types
let document = Node::Document(vec![
Node::heading(1, vec![Node::Text("Mixed List Example".to_string())]),
// Unordered list with both task and regular items
Node::UnorderedList(vec![
// Regular list item
ListItem::Unordered {
content: vec![Node::Paragraph(vec![
Node::Text("This is a regular list item".to_string())
])],
},
// Task list item
ListItem::Task {
status: TaskListStatus::Unchecked,
content: vec![Node::Paragraph(vec![
Node::Text("This is a task list item".to_string())
])],
},
// Another regular list item
ListItem::Unordered {
content: vec![Node::Paragraph(vec![
Node::Text("Another regular item".to_string())
])],
},
// Completed task
ListItem::Task {
status: TaskListStatus::Checked,
content: vec![Node::Paragraph(vec![
Node::Text("A completed task".to_string())
])],
},
]),
// Also works with ordered lists
Node::heading(2, vec![Node::Text("With Ordered Lists".to_string())]),
Node::OrderedList {
start: 1,
items: vec![
// Regular ordered item
ListItem::Ordered {
number: None,
content: vec![Node::Paragraph(vec![
Node::Text("First ordered item".to_string())
])],
},
// Task item in ordered list
ListItem::Task {
status: TaskListStatus::Unchecked,
content: vec![Node::Paragraph(vec![
Node::Text("Task in ordered list".to_string())
])],
},
// Another regular ordered item
ListItem::Ordered {
number: None,
content: vec![Node::Paragraph(vec![
Node::Text("Another ordered item".to_string())
])],
},
],
},
]);
// Configure writer with GFM task lists enabled
let options = WriterOptionsBuilder::new()
.gfm_tasklists(true)
.build();
let mut writer = CommonMarkWriter::with_options(options);
writer.write(&document)?;
let markdown = writer.into_string();
// Print the generated markdown
println!("{}", markdown);
Ok(())
}
With GFM enabled, this produces:
markdown
# Mixed List Example
- This is a regular list item
- [ ] This is a task list item
- Another regular item
- [x] A completed task
## With Ordered Lists
1. First ordered item
2. [ ] Task in ordered list
3. Another ordered item
Task List Best Practices
- Use task lists for actionable items: Task lists are best for tracking to-do items, rather than general information
- Keep task descriptions concise: Brief, clear descriptions work best in task lists
- Use nesting for hierarchical tasks: Group related sub-tasks under parent tasks
- Combine with other Markdown elements: Task list descriptions can include other formatting like emphasis or links
- Consider state representation: Checked items typically represent completed tasks, use them consistently
Implementation Notes
When implementing task lists:
- Remember to enable the
gfm
feature in yourCargo.toml
- Use the
WriterOptionsBuilder
to enable GFM task lists - Task lists can be nested within other lists
- Task items work in both ordered and unordered lists