Skip to content

Commit

Permalink
implement task lists
Browse files Browse the repository at this point in the history
closes jgm#3051
  • Loading branch information
mb21 committed Dec 10, 2018
1 parent 9dd4b30 commit 197df4a
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 6 deletions.
9 changes: 8 additions & 1 deletion MANUAL.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,13 @@ If default list markers are desired, use `#.`:
#. two
#. three

#### Extension: `tasklist` ####

Pandoc supports task lists, using the syntax of GitHub-Flavored Markdown.

- [ ] an unchecked task list item
- [x] checked item


### Definition lists ###

Expand Down Expand Up @@ -4223,7 +4230,7 @@ variants are supported:
: `pipe_tables`, `raw_html`, `fenced_code_blocks`, `auto_identifiers`,
`gfm_auto_identifiers`, `backtick_code_blocks`,
`autolink_bare_uris`, `space_in_atx_header`,
`intraword_underscores`, `strikeout`, `emoji`,
`intraword_underscores`, `strikeout`, `tasklist`, `emoji`,
`shortcut_reference_links`, `angle_brackets_escapable`,
`lists_without_preceding_blankline`.

Expand Down
3 changes: 3 additions & 0 deletions src/Text/Pandoc/Extensions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ data Extension =
| Ext_subscript -- ^ Subscript using ~this~ syntax
| Ext_superscript -- ^ Superscript using ^this^ syntax
| Ext_styles -- ^ Read styles that pandoc doesn't know
| Ext_tasklist -- ^ Parse certain list items as task list items
| Ext_table_captions -- ^ Pandoc-style table captions
| Ext_tex_math_dollars -- ^ TeX math between $..$ or $$..$$
| Ext_tex_math_double_backslash -- ^ TeX math btw \\(..\\) \\[..\\]
Expand Down Expand Up @@ -215,6 +216,7 @@ pandocExtensions = extensionsFromList
, Ext_strikeout
, Ext_superscript
, Ext_subscript
, Ext_tasklist
, Ext_auto_identifiers
, Ext_header_attributes
, Ext_link_attributes
Expand Down Expand Up @@ -274,6 +276,7 @@ githubMarkdownExtensions = extensionsFromList
, Ext_space_in_atx_header
, Ext_intraword_underscores
, Ext_strikeout
, Ext_tasklist
, Ext_emoji
, Ext_lists_without_preceding_blankline
, Ext_shortcut_reference_links
Expand Down
11 changes: 10 additions & 1 deletion src/Text/Pandoc/Readers/Markdown.hs
Original file line number Diff line number Diff line change
Expand Up @@ -946,8 +946,17 @@ listItem :: PandocMonad m
-> MarkdownParser m a
-> MarkdownParser m (F Blocks)
listItem fourSpaceRule start = try $ do
(first, continuationIndent) <- rawListItem fourSpaceRule start
(firstLine, continuationIndent) <- rawListItem fourSpaceRule start
continuations <- many (listContinuation continuationIndent)
exts <- getOption readerExtensions
let first = if Ext_tasklist `extensionEnabled` exts
then let (prefx, rest) = splitAt 4 firstLine
in case prefx of
"[ ] " -> "" <> rest
"[x] " -> "" <> rest
"[X] " -> "" <> rest
_ -> firstLine
else firstLine
-- parsing with ListItemState forces markers at beginning of lines to
-- count as list item markers, even if not separated by blank space.
-- see definition of "endline"
Expand Down
22 changes: 20 additions & 2 deletions src/Text/Pandoc/Writers/HTML.hs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,24 @@ defList :: PandocMonad m
=> WriterOptions -> [Html] -> StateT WriterState m Html
defList opts items = toList H.dl opts (items ++ [nl opts])

listItemToHtml :: PandocMonad m
=> WriterOptions -> [Block] -> StateT WriterState m Html
listItemToHtml opts bls
| (Plain (Str "\9744":Space:is) : bs) <- bls = taskListItem False id is bs
| (Plain (Str "\9746":Space:is) : bs) <- bls = taskListItem True id is bs
| (Para (Str "\9744":Space:is) : bs) <- bls = taskListItem False H.p is bs
| (Para (Str "\9746":Space:is) : bs) <- bls = taskListItem True H.p is bs
| otherwise = blockListToHtml opts bls
where
taskListItem checked constr is bs = do
let checkbox = if checked
then checkbox' ! A.checked ""
else checkbox'
checkbox' = H.input ! A.type_ "checkbox" ! A.disabled "" >> nl opts
isContents <- inlineListToHtml opts is
bsContents <- blockListToHtml opts bs
return $ constr (checkbox <> isContents) <> bsContents

-- | Construct table of contents from list of elements.
tableOfContents :: PandocMonad m => WriterOptions -> [Element]
-> StateT WriterState m (Maybe Html)
Expand Down Expand Up @@ -824,10 +842,10 @@ blockToHtml opts (Header level attr@(_,classes,_) lst) = do
6 -> H.h6 contents'
_ -> H.p contents'
blockToHtml opts (BulletList lst) = do
contents <- mapM (blockListToHtml opts) lst
contents <- mapM (listItemToHtml opts) lst
unordList opts contents
blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do
contents <- mapM (blockListToHtml opts) lst
contents <- mapM (listItemToHtml opts) lst
html5 <- gets stHtml5
let numstyle' = case numstyle of
Example -> "decimal"
Expand Down
16 changes: 14 additions & 2 deletions src/Text/Pandoc/Writers/LaTeX.hs
Original file line number Diff line number Diff line change
Expand Up @@ -922,8 +922,20 @@ listItemToLaTeX lst
-- this will keep the typesetter from throwing an error.
| (Header{} :_) <- lst =
blockListToLaTeX lst >>= return . (text "\\item ~" $$) . nest 2
| otherwise = blockListToLaTeX lst >>= return . (text "\\item" $$) .
nest 2
| (Plain (Str "\9744":Space:is) : bs) <- lst = taskListItem False is bs
| (Plain (Str "\9746":Space:is) : bs) <- lst = taskListItem True is bs
| (Para (Str "\9744":Space:is) : bs) <- lst = taskListItem False is bs
| (Para (Str "\9746":Space:is) : bs) <- lst = taskListItem True is bs
| otherwise = blockListToLaTeX lst >>= return . listItem
where
listItem = (text "\\item" $$) . nest 2
taskListItem checked is bs = do
let checkbox = if checked
then "$\\boxtimes$ "
else "$\\square$ "
isContents <- inlineListToLaTeX is
bsContents <- blockListToLaTeX bs
return $ listItem $ checkbox <> isContents $+$ bsContents

defListItemToLaTeX :: PandocMonad m => ([Inline], [[Block]]) -> LW m Doc
defListItemToLaTeX (term, defs) = do
Expand Down
102 changes: 102 additions & 0 deletions test/command/task-list-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
tests adapted from <https://github.github.com/gfm/#task-list-items-extension->

```
% pandoc
- [ ] foo
- [x] bar
^D
<ul>
<li><input type="checkbox" disabled="" />
foo</li>
<li><input type="checkbox" disabled="" checked="" />
bar</li>
</ul>
```


```
% pandoc
- [x] foo
- [ ] bar
- [x] baz
- [ ] bim
^D
<ul>
<li><input type="checkbox" disabled="" checked="" />
foo<ul>
<li><input type="checkbox" disabled="" />
bar</li>
<li><input type="checkbox" disabled="" checked="" />
baz</li>
</ul></li>
<li><input type="checkbox" disabled="" />
bim</li>
</ul>
```


custom html task list test:

```
% pandoc
- [ ] unchecked
- plain item
- [x] checked
paragraph
1. [ ] ordered unchecked
2. [] plain item
3. [x] ordered checked
paragraph
- [ ] list item with a
second paragraph
- [x] checked
^D
<ul>
<li><input type="checkbox" disabled="" />
unchecked</li>
<li>plain item</li>
<li><input type="checkbox" disabled="" checked="" />
checked</li>
</ul>
<p>paragraph</p>
<ol type="1">
<li><input type="checkbox" disabled="" />
ordered unchecked</li>
<li>[] plain item</li>
<li><input type="checkbox" disabled="" checked="" />
ordered checked</li>
</ol>
<p>paragraph</p>
<ul>
<li><p><input type="checkbox" disabled="" />
list item with a</p><p>second paragraph</p></li>
<li><p><input type="checkbox" disabled="" checked="" />
checked</p></li>
</ul>
```

latex task list test:

```
% pandoc -t latex
- [ ] foo bar
baz
- [x] boo
^D
\begin{itemize}
\item
$\square$ foo bar
baz
\item
$\boxtimes$ boo
\end{itemize}
```

0 comments on commit 197df4a

Please sign in to comment.