diff --git a/MANUAL.txt b/MANUAL.txt index dca6291594d8..09ece2340afa 100644 --- a/MANUAL.txt +++ b/MANUAL.txt @@ -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 ### @@ -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`. diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs index f2599ed6d8df..9a1994027e28 100644 --- a/src/Text/Pandoc/Extensions.hs +++ b/src/Text/Pandoc/Extensions.hs @@ -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 \\(..\\) \\[..\\] @@ -215,6 +216,7 @@ pandocExtensions = extensionsFromList , Ext_strikeout , Ext_superscript , Ext_subscript + , Ext_tasklist , Ext_auto_identifiers , Ext_header_attributes , Ext_link_attributes @@ -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 diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs index 94d1157a6b7d..7bde1daa11e1 100644 --- a/src/Text/Pandoc/Readers/Markdown.hs +++ b/src/Text/Pandoc/Readers/Markdown.hs @@ -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" diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs index 8cdadca5b152..87f2ce499342 100644 --- a/src/Text/Pandoc/Writers/HTML.hs +++ b/src/Text/Pandoc/Writers/HTML.hs @@ -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) @@ -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" diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index ca8295f0a3db..cc309cdb516a 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -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 diff --git a/test/command/task-list-test.md b/test/command/task-list-test.md new file mode 100644 index 000000000000..9d89d500f196 --- /dev/null +++ b/test/command/task-list-test.md @@ -0,0 +1,102 @@ +tests adapted from + +``` +% pandoc +- [ ] foo +- [x] bar +^D + +``` + + +``` +% pandoc +- [x] foo + - [ ] bar + - [x] baz +- [ ] bim +^D + +``` + + +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 + +

paragraph

+
    +
  1. +ordered unchecked
  2. +
  3. [] plain item
  4. +
  5. +ordered checked
  6. +
+

paragraph

+ +``` + +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} +```