{-# LANGUAGE TupleSections #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
module Commonmark.Extensions.TaskList
( taskListSpec
, HasTaskList (..)
)
where
import Commonmark.Tokens
import Commonmark.Types
import Commonmark.Syntax
import Commonmark.Blocks
import Commonmark.SourceMap
import Commonmark.TokParsers
import Commonmark.Html
import Control.Monad (mzero)
import Control.Monad (when, guard)
import Data.List (sort)
import Data.Dynamic
import Data.Tree
import Text.Parsec
taskListSpec :: (Monad m, IsBlock il bl, IsInline il, HasTaskList il bl)
=> SyntaxSpec m il bl
taskListSpec :: SyntaxSpec m il bl
taskListSpec = SyntaxSpec m il bl
forall a. Monoid a => a
mempty
{ syntaxBlockSpecs :: [BlockSpec m il bl]
syntaxBlockSpecs = [BlockSpec m il bl
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl, HasTaskList il bl) =>
BlockSpec m il bl
taskListItemBlockSpec]
}
data ListData = ListData
{ ListData -> ListType
listType :: !ListType
, ListData -> ListSpacing
listSpacing :: !ListSpacing
} deriving (Int -> ListData -> ShowS
[ListData] -> ShowS
ListData -> String
(Int -> ListData -> ShowS)
-> (ListData -> String) -> ([ListData] -> ShowS) -> Show ListData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ListData] -> ShowS
$cshowList :: [ListData] -> ShowS
show :: ListData -> String
$cshow :: ListData -> String
showsPrec :: Int -> ListData -> ShowS
$cshowsPrec :: Int -> ListData -> ShowS
Show, ListData -> ListData -> Bool
(ListData -> ListData -> Bool)
-> (ListData -> ListData -> Bool) -> Eq ListData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ListData -> ListData -> Bool
$c/= :: ListData -> ListData -> Bool
== :: ListData -> ListData -> Bool
$c== :: ListData -> ListData -> Bool
Eq)
data ListItemData = ListItemData
{ ListItemData -> ListType
listItemType :: !ListType
, ListItemData -> Bool
listItemChecked :: !Bool
, ListItemData -> Int
listItemIndent :: !Int
, ListItemData -> Bool
listItemBlanksInside :: !Bool
, ListItemData -> Bool
listItemBlanksAtEnd :: !Bool
} deriving (Int -> ListItemData -> ShowS
[ListItemData] -> ShowS
ListItemData -> String
(Int -> ListItemData -> ShowS)
-> (ListItemData -> String)
-> ([ListItemData] -> ShowS)
-> Show ListItemData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ListItemData] -> ShowS
$cshowList :: [ListItemData] -> ShowS
show :: ListItemData -> String
$cshow :: ListItemData -> String
showsPrec :: Int -> ListItemData -> ShowS
$cshowsPrec :: Int -> ListItemData -> ShowS
Show, ListItemData -> ListItemData -> Bool
(ListItemData -> ListItemData -> Bool)
-> (ListItemData -> ListItemData -> Bool) -> Eq ListItemData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ListItemData -> ListItemData -> Bool
$c/= :: ListItemData -> ListItemData -> Bool
== :: ListItemData -> ListItemData -> Bool
$c== :: ListItemData -> ListItemData -> Bool
Eq)
taskListBlockSpec :: (Monad m, IsBlock il bl,
HasTaskList il bl) => BlockSpec m il bl
taskListBlockSpec :: BlockSpec m il bl
taskListBlockSpec = $WBlockSpec :: forall (m :: * -> *) il bl.
Text
-> BlockParser m il bl BlockStartResult
-> (BlockSpec m il bl -> Bool)
-> Bool
-> Bool
-> (BlockNode m il bl
-> BlockParser m il bl (SourcePos, BlockNode m il bl))
-> (BlockNode m il bl -> BlockParser m il bl bl)
-> (BlockNode m il bl
-> BlockNode m il bl -> BlockParser m il bl (BlockNode m il bl))
-> BlockSpec m il bl
BlockSpec
{ blockType :: Text
blockType = "TaskList"
, blockStart :: BlockParser m il bl BlockStartResult
blockStart = BlockParser m il bl BlockStartResult
forall (m :: * -> *) a. MonadPlus m => m a
mzero
, blockCanContain :: BlockSpec m il bl -> Bool
blockCanContain = \sp :: BlockSpec m il bl
sp -> BlockSpec m il bl -> Text
forall (m :: * -> *) il bl. BlockSpec m il bl -> Text
blockType BlockSpec m il bl
sp Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== "TaskListItem"
, blockContainsLines :: Bool
blockContainsLines = Bool
False
, blockParagraph :: Bool
blockParagraph = Bool
False
, blockContinue :: BlockNode m il bl
-> BlockParser m il bl (SourcePos, BlockNode m il bl)
blockContinue = \n :: BlockNode m il bl
n -> (,BlockNode m il bl
n) (SourcePos -> (SourcePos, BlockNode m il bl))
-> ParsecT [Tok] (BPState m il bl) m SourcePos
-> BlockParser m il bl (SourcePos, BlockNode m il bl)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT [Tok] (BPState m il bl) m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
, blockConstructor :: BlockNode m il bl -> BlockParser m il bl bl
blockConstructor = \node :: BlockNode m il bl
node -> do
let ListData lt :: ListType
lt ls :: ListSpacing
ls = Dynamic -> ListData -> ListData
forall a. Typeable a => Dynamic -> a -> a
fromDyn (BlockData m il bl -> Dynamic
forall (m :: * -> *) il bl. BlockData m il bl -> Dynamic
blockData (BlockNode m il bl -> BlockData m il bl
forall a. Tree a -> a
rootLabel BlockNode m il bl
node))
(ListType -> ListSpacing -> ListData
ListData (Char -> ListType
BulletList '*') ListSpacing
TightList)
let getCheckedStatus :: Tree (BlockData m il bl) -> Bool
getCheckedStatus n :: Tree (BlockData m il bl)
n =
ListItemData -> Bool
listItemChecked (ListItemData -> Bool) -> ListItemData -> Bool
forall a b. (a -> b) -> a -> b
$
Dynamic -> ListItemData -> ListItemData
forall a. Typeable a => Dynamic -> a -> a
fromDyn (BlockData m il bl -> Dynamic
forall (m :: * -> *) il bl. BlockData m il bl -> Dynamic
blockData (Tree (BlockData m il bl) -> BlockData m il bl
forall a. Tree a -> a
rootLabel Tree (BlockData m il bl)
n))
(ListType -> Bool -> Int -> Bool -> Bool -> ListItemData
ListItemData (Char -> ListType
BulletList '*') Bool
False 0 Bool
False Bool
False)
let checkedStatus :: [Bool]
checkedStatus = (BlockNode m il bl -> Bool) -> [BlockNode m il bl] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map BlockNode m il bl -> Bool
forall (m :: * -> *) il bl. Tree (BlockData m il bl) -> Bool
getCheckedStatus ([BlockNode m il bl] -> [Bool]) -> [BlockNode m il bl] -> [Bool]
forall a b. (a -> b) -> a -> b
$ BlockNode m il bl -> [BlockNode m il bl]
forall a. Tree a -> Forest a
subForest BlockNode m il bl
node
ListType -> ListSpacing -> [(Bool, bl)] -> bl
forall il bl.
HasTaskList il bl =>
ListType -> ListSpacing -> [(Bool, bl)] -> bl
taskList ListType
lt ListSpacing
ls ([(Bool, bl)] -> bl) -> ([bl] -> [(Bool, bl)]) -> [bl] -> bl
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Bool] -> [bl] -> [(Bool, bl)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Bool]
checkedStatus ([bl] -> bl)
-> ParsecT [Tok] (BPState m il bl) m [bl] -> BlockParser m il bl bl
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BlockNode m il bl -> ParsecT [Tok] (BPState m il bl) m [bl]
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl) =>
BlockNode m il bl -> BlockParser m il bl [bl]
renderChildren BlockNode m il bl
node
, blockFinalize :: BlockNode m il bl
-> BlockNode m il bl -> BlockParser m il bl (BlockNode m il bl)
blockFinalize = \(Node cdata :: BlockData m il bl
cdata children :: [BlockNode m il bl]
children) parent :: BlockNode m il bl
parent -> do
let ListData lt :: ListType
lt _ = Dynamic -> ListData -> ListData
forall a. Typeable a => Dynamic -> a -> a
fromDyn (BlockData m il bl -> Dynamic
forall (m :: * -> *) il bl. BlockData m il bl -> Dynamic
blockData BlockData m il bl
cdata)
(ListType -> ListSpacing -> ListData
ListData (Char -> ListType
BulletList '*') ListSpacing
TightList)
let getListItemData :: Tree (BlockData m il bl) -> ListItemData
getListItemData (Node d :: BlockData m il bl
d _) =
Dynamic -> ListItemData -> ListItemData
forall a. Typeable a => Dynamic -> a -> a
fromDyn (BlockData m il bl -> Dynamic
forall (m :: * -> *) il bl. BlockData m il bl -> Dynamic
blockData BlockData m il bl
d)
(ListType -> Bool -> Int -> Bool -> Bool -> ListItemData
ListItemData (Char -> ListType
BulletList '*') Bool
False 0 Bool
False Bool
False)
let childrenData :: [ListItemData]
childrenData = (BlockNode m il bl -> ListItemData)
-> [BlockNode m il bl] -> [ListItemData]
forall a b. (a -> b) -> [a] -> [b]
map BlockNode m il bl -> ListItemData
forall (m :: * -> *) il bl.
Tree (BlockData m il bl) -> ListItemData
getListItemData [BlockNode m il bl]
children
let ls :: ListSpacing
ls = case [ListItemData]
childrenData of
c :: ListItemData
c:cs :: [ListItemData]
cs | (ListItemData -> Bool) -> [ListItemData] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ListItemData -> Bool
listItemBlanksInside (ListItemData
cListItemData -> [ListItemData] -> [ListItemData]
forall a. a -> [a] -> [a]
:[ListItemData]
cs) Bool -> Bool -> Bool
||
(Bool -> Bool
not ([ListItemData] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ListItemData]
cs) Bool -> Bool -> Bool
&&
(ListItemData -> Bool) -> [ListItemData] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ListItemData -> Bool
listItemBlanksAtEnd [ListItemData]
cs)
-> ListSpacing
LooseList
_ -> ListSpacing
TightList
[Int]
blockBlanks' <- case [ListItemData]
childrenData of
c :: ListItemData
c:_ | ListItemData -> Bool
listItemBlanksAtEnd ListItemData
c -> do
Int
curline <- SourcePos -> Int
sourceLine (SourcePos -> Int)
-> ParsecT [Tok] (BPState m il bl) m SourcePos
-> ParsecT [Tok] (BPState m il bl) m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT [Tok] (BPState m il bl) m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
[Int] -> ParsecT [Tok] (BPState m il bl) m [Int]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Int] -> ParsecT [Tok] (BPState m il bl) m [Int])
-> [Int] -> ParsecT [Tok] (BPState m il bl) m [Int]
forall a b. (a -> b) -> a -> b
$! Int
curline Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: BlockData m il bl -> [Int]
forall (m :: * -> *) il bl. BlockData m il bl -> [Int]
blockBlanks BlockData m il bl
cdata
_ -> [Int] -> ParsecT [Tok] (BPState m il bl) m [Int]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Int] -> ParsecT [Tok] (BPState m il bl) m [Int])
-> [Int] -> ParsecT [Tok] (BPState m il bl) m [Int]
forall a b. (a -> b) -> a -> b
$! BlockData m il bl -> [Int]
forall (m :: * -> *) il bl. BlockData m il bl -> [Int]
blockBlanks BlockData m il bl
cdata
let ldata' :: Dynamic
ldata' = ListData -> Dynamic
forall a. Typeable a => a -> Dynamic
toDyn (ListType -> ListSpacing -> ListData
ListData ListType
lt ListSpacing
ls)
let totight :: Tree (BlockData m il bl) -> Tree (BlockData m il bl)
totight (Node nd :: BlockData m il bl
nd cs :: Forest (BlockData m il bl)
cs)
| BlockSpec m il bl -> Text
forall (m :: * -> *) il bl. BlockSpec m il bl -> Text
blockType (BlockData m il bl -> BlockSpec m il bl
forall (m :: * -> *) il bl. BlockData m il bl -> BlockSpec m il bl
blockSpec BlockData m il bl
nd) Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== "Paragraph"
= BlockData m il bl
-> Forest (BlockData m il bl) -> Tree (BlockData m il bl)
forall a. a -> Forest a -> Tree a
Node BlockData m il bl
nd{ blockSpec :: BlockSpec m il bl
blockSpec = BlockSpec m il bl
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl) =>
BlockSpec m il bl
plainSpec } Forest (BlockData m il bl)
cs
| Bool
otherwise = BlockData m il bl
-> Forest (BlockData m il bl) -> Tree (BlockData m il bl)
forall a. a -> Forest a -> Tree a
Node BlockData m il bl
nd Forest (BlockData m il bl)
cs
let childrenToTight :: Tree (BlockData m il bl) -> Tree (BlockData m il bl)
childrenToTight (Node nd :: BlockData m il bl
nd cs :: Forest (BlockData m il bl)
cs) = BlockData m il bl
-> Forest (BlockData m il bl) -> Tree (BlockData m il bl)
forall a. a -> Forest a -> Tree a
Node BlockData m il bl
nd ((Tree (BlockData m il bl) -> Tree (BlockData m il bl))
-> Forest (BlockData m il bl) -> Forest (BlockData m il bl)
forall a b. (a -> b) -> [a] -> [b]
map Tree (BlockData m il bl) -> Tree (BlockData m il bl)
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl) =>
Tree (BlockData m il bl) -> Tree (BlockData m il bl)
totight Forest (BlockData m il bl)
cs)
let children' :: [BlockNode m il bl]
children' =
if ListSpacing
ls ListSpacing -> ListSpacing -> Bool
forall a. Eq a => a -> a -> Bool
== ListSpacing
TightList
then (BlockNode m il bl -> BlockNode m il bl)
-> [BlockNode m il bl] -> [BlockNode m il bl]
forall a b. (a -> b) -> [a] -> [b]
map BlockNode m il bl -> BlockNode m il bl
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl) =>
Tree (BlockData m il bl) -> Tree (BlockData m il bl)
childrenToTight [BlockNode m il bl]
children
else [BlockNode m il bl]
children
BlockNode m il bl
-> BlockNode m il bl -> BlockParser m il bl (BlockNode m il bl)
forall (m :: * -> *) il bl.
Monad m =>
BlockNode m il bl
-> BlockNode m il bl -> BlockParser m il bl (BlockNode m il bl)
defaultFinalizer (BlockData m il bl -> [BlockNode m il bl] -> BlockNode m il bl
forall a. a -> Forest a -> Tree a
Node BlockData m il bl
cdata{ blockData :: Dynamic
blockData = Dynamic
ldata'
, blockBlanks :: [Int]
blockBlanks = [Int]
blockBlanks' } [BlockNode m il bl]
children')
BlockNode m il bl
parent
}
taskListItemBlockSpec :: (Monad m, IsBlock il bl, HasTaskList il bl)
=> BlockSpec m il bl
taskListItemBlockSpec :: BlockSpec m il bl
taskListItemBlockSpec = $WBlockSpec :: forall (m :: * -> *) il bl.
Text
-> BlockParser m il bl BlockStartResult
-> (BlockSpec m il bl -> Bool)
-> Bool
-> Bool
-> (BlockNode m il bl
-> BlockParser m il bl (SourcePos, BlockNode m il bl))
-> (BlockNode m il bl -> BlockParser m il bl bl)
-> (BlockNode m il bl
-> BlockNode m il bl -> BlockParser m il bl (BlockNode m il bl))
-> BlockSpec m il bl
BlockSpec
{ blockType :: Text
blockType = "TaskListItem"
, blockStart :: BlockParser m il bl BlockStartResult
blockStart = do
(pos :: SourcePos
pos, lidata :: ListItemData
lidata) <- BlockParser m il bl (SourcePos, ListItemData)
forall (m :: * -> *) il bl.
Monad m =>
BlockParser m il bl (SourcePos, ListItemData)
itemStart
let linode :: Tree (BlockData m il bl)
linode = BlockData m il bl
-> Forest (BlockData m il bl) -> Tree (BlockData m il bl)
forall a. a -> Forest a -> Tree a
Node (BlockSpec m il bl -> BlockData m il bl
forall (m :: * -> *) il bl. BlockSpec m il bl -> BlockData m il bl
defBlockData BlockSpec m il bl
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl, HasTaskList il bl) =>
BlockSpec m il bl
taskListItemBlockSpec){
blockData :: Dynamic
blockData = ListItemData -> Dynamic
forall a. Typeable a => a -> Dynamic
toDyn ListItemData
lidata,
blockStartPos :: [SourcePos]
blockStartPos = [SourcePos
pos] } []
let listdata :: ListData
listdata = $WListData :: ListType -> ListSpacing -> ListData
ListData{
listType :: ListType
listType = ListItemData -> ListType
listItemType ListItemData
lidata
, listSpacing :: ListSpacing
listSpacing = ListSpacing
TightList }
let listnode :: Tree (BlockData m il bl)
listnode = BlockData m il bl
-> Forest (BlockData m il bl) -> Tree (BlockData m il bl)
forall a. a -> Forest a -> Tree a
Node (BlockSpec m il bl -> BlockData m il bl
forall (m :: * -> *) il bl. BlockSpec m il bl -> BlockData m il bl
defBlockData BlockSpec m il bl
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl, HasTaskList il bl) =>
BlockSpec m il bl
taskListBlockSpec){
blockData :: Dynamic
blockData = ListData -> Dynamic
forall a. Typeable a => a -> Dynamic
toDyn ListData
listdata,
blockStartPos :: [SourcePos]
blockStartPos = [SourcePos
pos] } []
(cur :: Tree (BlockData m il bl)
cur:_) <- BPState m il bl -> Forest (BlockData m il bl)
forall (m :: * -> *) il bl. BPState m il bl -> [BlockNode m il bl]
nodeStack (BPState m il bl -> Forest (BlockData m il bl))
-> ParsecT [Tok] (BPState m il bl) m (BPState m il bl)
-> ParsecT [Tok] (BPState m il bl) m (Forest (BlockData m il bl))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT [Tok] (BPState m il bl) m (BPState m il bl)
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
Bool
-> ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (BlockSpec m il bl -> Bool
forall (m :: * -> *) il bl. BlockSpec m il bl -> Bool
blockParagraph (Tree (BlockData m il bl) -> BlockSpec m il bl
forall (m :: * -> *) il bl. BlockNode m il bl -> BlockSpec m il bl
bspec Tree (BlockData m il bl)
cur)) (ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m ())
-> ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m ()
forall a b. (a -> b) -> a -> b
$ do
Bool -> ParsecT [Tok] (BPState m il bl) m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ParsecT [Tok] (BPState m il bl) m ())
-> Bool -> ParsecT [Tok] (BPState m il bl) m ()
forall a b. (a -> b) -> a -> b
$ case ListData -> ListType
listType ListData
listdata of
BulletList _ -> Bool
True
OrderedList 1 Decimal _ -> Bool
True
_ -> Bool
False
ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m ()
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy ParsecT [Tok] (BPState m il bl) m ()
forall (m :: * -> *) s. Monad m => ParsecT [Tok] s m ()
blankLine
let curdata :: ListData
curdata = Dynamic -> ListData -> ListData
forall a. Typeable a => Dynamic -> a -> a
fromDyn (BlockData m il bl -> Dynamic
forall (m :: * -> *) il bl. BlockData m il bl -> Dynamic
blockData (Tree (BlockData m il bl) -> BlockData m il bl
forall a. Tree a -> a
rootLabel Tree (BlockData m il bl)
cur))
(ListType -> ListSpacing -> ListData
ListData (Char -> ListType
BulletList '*') ListSpacing
TightList)
let matchesList :: ListType -> ListType -> Bool
matchesList (BulletList c :: Char
c) (BulletList d :: Char
d) = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
d
matchesList (OrderedList _ e1 :: EnumeratorType
e1 d1 :: DelimiterType
d1)
(OrderedList _ e2 :: EnumeratorType
e2 d2 :: DelimiterType
d2) = EnumeratorType
e1 EnumeratorType -> EnumeratorType -> Bool
forall a. Eq a => a -> a -> Bool
== EnumeratorType
e2 Bool -> Bool -> Bool
&& DelimiterType
d1 DelimiterType -> DelimiterType -> Bool
forall a. Eq a => a -> a -> Bool
== DelimiterType
d2
matchesList _ _ = Bool
False
case BlockSpec m il bl -> Text
forall (m :: * -> *) il bl. BlockSpec m il bl -> Text
blockType (Tree (BlockData m il bl) -> BlockSpec m il bl
forall (m :: * -> *) il bl. BlockNode m il bl -> BlockSpec m il bl
bspec Tree (BlockData m il bl)
cur) of
"TaskList" | ListData -> ListType
listType ListData
curdata ListType -> ListType -> Bool
`matchesList`
ListItemData -> ListType
listItemType ListItemData
lidata
-> Tree (BlockData m il bl) -> ParsecT [Tok] (BPState m il bl) m ()
forall (m :: * -> *) bl il.
Monad m =>
BlockNode m bl il -> BlockParser m bl il ()
addNodeToStack Tree (BlockData m il bl)
linode
_ -> Tree (BlockData m il bl) -> ParsecT [Tok] (BPState m il bl) m ()
forall (m :: * -> *) bl il.
Monad m =>
BlockNode m bl il -> BlockParser m bl il ()
addNodeToStack Tree (BlockData m il bl)
listnode ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Tree (BlockData m il bl) -> ParsecT [Tok] (BPState m il bl) m ()
forall (m :: * -> *) bl il.
Monad m =>
BlockNode m bl il -> BlockParser m bl il ()
addNodeToStack Tree (BlockData m il bl)
linode
BlockStartResult -> BlockParser m il bl BlockStartResult
forall (m :: * -> *) a. Monad m => a -> m a
return BlockStartResult
BlockStartMatch
, blockCanContain :: BlockSpec m il bl -> Bool
blockCanContain = Bool -> BlockSpec m il bl -> Bool
forall a b. a -> b -> a
const Bool
True
, blockContainsLines :: Bool
blockContainsLines = Bool
False
, blockParagraph :: Bool
blockParagraph = Bool
False
, blockContinue :: Tree (BlockData m il bl)
-> BlockParser m il bl (SourcePos, Tree (BlockData m il bl))
blockContinue = \node :: Tree (BlockData m il bl)
node@(Node ndata :: BlockData m il bl
ndata children :: Forest (BlockData m il bl)
children) -> do
let lidata :: ListItemData
lidata = Dynamic -> ListItemData -> ListItemData
forall a. Typeable a => Dynamic -> a -> a
fromDyn (BlockData m il bl -> Dynamic
forall (m :: * -> *) il bl. BlockData m il bl -> Dynamic
blockData BlockData m il bl
ndata)
(ListType -> Bool -> Int -> Bool -> Bool -> ListItemData
ListItemData (Char -> ListType
BulletList '*') Bool
False 0
Bool
False Bool
False)
Bool -> ParsecT [Tok] (BPState m il bl) m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ParsecT [Tok] (BPState m il bl) m ())
-> Bool -> ParsecT [Tok] (BPState m il bl) m ()
forall a b. (a -> b) -> a -> b
$ [Int] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (BlockData m il bl -> [Int]
forall (m :: * -> *) il bl. BlockData m il bl -> [Int]
blockBlanks BlockData m il bl
ndata) Bool -> Bool -> Bool
||
Bool -> Bool
not (Forest (BlockData m il bl) -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Forest (BlockData m il bl)
children)
SourcePos
pos <- ParsecT [Tok] (BPState m il bl) m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
Int -> ParsecT [Tok] (BPState m il bl) m Int
forall (m :: * -> *) u. Monad m => Int -> ParsecT [Tok] u m Int
gobbleSpaces (ListItemData -> Int
listItemIndent ListItemData
lidata) ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m Int
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> 0 Int
-> ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m Int
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m ()
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead ParsecT [Tok] (BPState m il bl) m ()
forall (m :: * -> *) s. Monad m => ParsecT [Tok] s m ()
blankLine
(SourcePos, Tree (BlockData m il bl))
-> BlockParser m il bl (SourcePos, Tree (BlockData m il bl))
forall (m :: * -> *) a. Monad m => a -> m a
return ((SourcePos, Tree (BlockData m il bl))
-> BlockParser m il bl (SourcePos, Tree (BlockData m il bl)))
-> (SourcePos, Tree (BlockData m il bl))
-> BlockParser m il bl (SourcePos, Tree (BlockData m il bl))
forall a b. (a -> b) -> a -> b
$! (SourcePos
pos, Tree (BlockData m il bl)
node)
, blockConstructor :: Tree (BlockData m il bl) -> BlockParser m il bl bl
blockConstructor = ([bl] -> bl)
-> ParsecT [Tok] (BPState m il bl) m [bl] -> BlockParser m il bl bl
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [bl] -> bl
forall a. Monoid a => [a] -> a
mconcat (ParsecT [Tok] (BPState m il bl) m [bl] -> BlockParser m il bl bl)
-> (Tree (BlockData m il bl)
-> ParsecT [Tok] (BPState m il bl) m [bl])
-> Tree (BlockData m il bl)
-> BlockParser m il bl bl
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tree (BlockData m il bl) -> ParsecT [Tok] (BPState m il bl) m [bl]
forall (m :: * -> *) il bl.
(Monad m, IsBlock il bl) =>
BlockNode m il bl -> BlockParser m il bl [bl]
renderChildren
, blockFinalize :: Tree (BlockData m il bl)
-> Tree (BlockData m il bl)
-> BlockParser m il bl (Tree (BlockData m il bl))
blockFinalize = \(Node cdata :: BlockData m il bl
cdata children :: Forest (BlockData m il bl)
children) parent :: Tree (BlockData m il bl)
parent -> do
let lidata :: ListItemData
lidata = Dynamic -> ListItemData -> ListItemData
forall a. Typeable a => Dynamic -> a -> a
fromDyn (BlockData m il bl -> Dynamic
forall (m :: * -> *) il bl. BlockData m il bl -> Dynamic
blockData BlockData m il bl
cdata)
(ListType -> Bool -> Int -> Bool -> Bool -> ListItemData
ListItemData (Char -> ListType
BulletList '*') Bool
False
0 Bool
False Bool
False)
let blanks :: [Int]
blanks = [Int] -> [Int]
removeConsecutive ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$
[[Int]] -> [Int]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Int]] -> [Int]) -> [[Int]] -> [Int]
forall a b. (a -> b) -> a -> b
$ BlockData m il bl -> [Int]
forall (m :: * -> *) il bl. BlockData m il bl -> [Int]
blockBlanks BlockData m il bl
cdata [Int] -> [[Int]] -> [[Int]]
forall a. a -> [a] -> [a]
:
(Tree (BlockData m il bl) -> [Int])
-> Forest (BlockData m il bl) -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map (BlockData m il bl -> [Int]
forall (m :: * -> *) il bl. BlockData m il bl -> [Int]
blockBlanks (BlockData m il bl -> [Int])
-> (Tree (BlockData m il bl) -> BlockData m il bl)
-> Tree (BlockData m il bl)
-> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tree (BlockData m il bl) -> BlockData m il bl
forall a. Tree a -> a
rootLabel)
((Tree (BlockData m il bl) -> Bool)
-> Forest (BlockData m il bl) -> Forest (BlockData m il bl)
forall a. (a -> Bool) -> [a] -> [a]
filter ((Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== "List") (Text -> Bool)
-> (Tree (BlockData m il bl) -> Text)
-> Tree (BlockData m il bl)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BlockSpec m il bl -> Text
forall (m :: * -> *) il bl. BlockSpec m il bl -> Text
blockType (BlockSpec m il bl -> Text)
-> (Tree (BlockData m il bl) -> BlockSpec m il bl)
-> Tree (BlockData m il bl)
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
BlockData m il bl -> BlockSpec m il bl
forall (m :: * -> *) il bl. BlockData m il bl -> BlockSpec m il bl
blockSpec (BlockData m il bl -> BlockSpec m il bl)
-> (Tree (BlockData m il bl) -> BlockData m il bl)
-> Tree (BlockData m il bl)
-> BlockSpec m il bl
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tree (BlockData m il bl) -> BlockData m il bl
forall a. Tree a -> a
rootLabel) Forest (BlockData m il bl)
children)
Int
curline <- SourcePos -> Int
sourceLine (SourcePos -> Int)
-> ParsecT [Tok] (BPState m il bl) m SourcePos
-> ParsecT [Tok] (BPState m il bl) m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT [Tok] (BPState m il bl) m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
let blanksAtEnd :: Bool
blanksAtEnd = case [Int]
blanks of
(l :: Int
l:_) -> Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
curline Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1
_ -> Bool
False
let blanksInside :: Bool
blanksInside = case [Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
blanks of
n :: Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1 -> Bool
True
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1 -> Bool -> Bool
not Bool
blanksAtEnd
| Bool
otherwise -> Bool
False
let lidata' :: Dynamic
lidata' = ListItemData -> Dynamic
forall a. Typeable a => a -> Dynamic
toDyn (ListItemData -> Dynamic) -> ListItemData -> Dynamic
forall a b. (a -> b) -> a -> b
$ ListItemData
lidata{ listItemBlanksInside :: Bool
listItemBlanksInside = Bool
blanksInside
, listItemBlanksAtEnd :: Bool
listItemBlanksAtEnd = Bool
blanksAtEnd }
Tree (BlockData m il bl)
-> Tree (BlockData m il bl)
-> BlockParser m il bl (Tree (BlockData m il bl))
forall (m :: * -> *) il bl.
Monad m =>
BlockNode m il bl
-> BlockNode m il bl -> BlockParser m il bl (BlockNode m il bl)
defaultFinalizer (BlockData m il bl
-> Forest (BlockData m il bl) -> Tree (BlockData m il bl)
forall a. a -> Forest a -> Tree a
Node BlockData m il bl
cdata{ blockData :: Dynamic
blockData = Dynamic
lidata' } Forest (BlockData m il bl)
children)
Tree (BlockData m il bl)
parent
}
removeConsecutive :: [Int] -> [Int]
removeConsecutive :: [Int] -> [Int]
removeConsecutive (x :: Int
x:y :: Int
y:zs :: [Int]
zs)
| Int
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
y Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1 = [Int] -> [Int]
removeConsecutive (Int
yInt -> [Int] -> [Int]
forall a. a -> [a] -> [a]
:[Int]
zs)
removeConsecutive xs :: [Int]
xs = [Int]
xs
itemStart :: Monad m
=> BlockParser m il bl (SourcePos, ListItemData)
itemStart :: BlockParser m il bl (SourcePos, ListItemData)
itemStart = do
Int
beforecol <- SourcePos -> Int
sourceColumn (SourcePos -> Int)
-> ParsecT [Tok] (BPState m il bl) m SourcePos
-> ParsecT [Tok] (BPState m il bl) m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT [Tok] (BPState m il bl) m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
Int -> ParsecT [Tok] (BPState m il bl) m Int
forall (m :: * -> *) u. Monad m => Int -> ParsecT [Tok] u m Int
gobbleUpToSpaces 3
SourcePos
pos <- ParsecT [Tok] (BPState m il bl) m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
ListType
ty <- BlockParser m il bl ListType
forall (m :: * -> *) il bl. Monad m => BlockParser m il bl ListType
bulletListMarker
Int
aftercol <- SourcePos -> Int
sourceColumn (SourcePos -> Int)
-> ParsecT [Tok] (BPState m il bl) m SourcePos
-> ParsecT [Tok] (BPState m il bl) m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT [Tok] (BPState m il bl) m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
Bool
checked <- BlockParser m il bl Bool
forall (m :: * -> *) il bl. Monad m => BlockParser m il bl Bool
parseCheckbox
ParsecT [Tok] (BPState m il bl) m [Tok]
-> ParsecT [Tok] (BPState m il bl) m [Tok]
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead ParsecT [Tok] (BPState m il bl) m [Tok]
forall (m :: * -> *) s. Monad m => ParsecT [Tok] s m [Tok]
whitespace
Int
numspaces <- ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m Int
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Int -> ParsecT [Tok] (BPState m il bl) m Int
forall (m :: * -> *) u. Monad m => Int -> ParsecT [Tok] u m Int
gobbleUpToSpaces 4 ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m ()
-> ParsecT [Tok] (BPState m il bl) m Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT [Tok] (BPState m il bl) m [Tok]
-> ParsecT [Tok] (BPState m il bl) m ()
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy ParsecT [Tok] (BPState m il bl) m [Tok]
forall (m :: * -> *) s. Monad m => ParsecT [Tok] s m [Tok]
whitespace)
ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m Int
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Int -> ParsecT [Tok] (BPState m il bl) m Int
forall (m :: * -> *) u. Monad m => Int -> ParsecT [Tok] u m Int
gobbleSpaces 1
ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m Int
-> ParsecT [Tok] (BPState m il bl) m Int
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> 1 Int
-> ParsecT [Tok] (BPState m il bl) m Tok
-> ParsecT [Tok] (BPState m il bl) m Int
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ParsecT [Tok] (BPState m il bl) m Tok
-> ParsecT [Tok] (BPState m il bl) m Tok
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead ParsecT [Tok] (BPState m il bl) m Tok
forall (m :: * -> *) s. Monad m => ParsecT [Tok] s m Tok
lineEnd
(SourcePos, ListItemData)
-> BlockParser m il bl (SourcePos, ListItemData)
forall (m :: * -> *) a. Monad m => a -> m a
return ((SourcePos, ListItemData)
-> BlockParser m il bl (SourcePos, ListItemData))
-> (SourcePos, ListItemData)
-> BlockParser m il bl (SourcePos, ListItemData)
forall a b. (a -> b) -> a -> b
$! (SourcePos
pos, $WListItemData :: ListType -> Bool -> Int -> Bool -> Bool -> ListItemData
ListItemData{
listItemType :: ListType
listItemType = ListType
ty
, listItemChecked :: Bool
listItemChecked = Bool
checked
, listItemIndent :: Int
listItemIndent = (Int
aftercol Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
beforecol) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
numspaces
, listItemBlanksInside :: Bool
listItemBlanksInside = Bool
False
, listItemBlanksAtEnd :: Bool
listItemBlanksAtEnd = Bool
False
})
parseCheckbox :: Monad m => BlockParser m il bl Bool
parseCheckbox :: BlockParser m il bl Bool
parseCheckbox = do
Int -> ParsecT [Tok] (BPState m il bl) m Int
forall (m :: * -> *) u. Monad m => Int -> ParsecT [Tok] u m Int
gobbleUpToSpaces 3
Char -> ParsecT [Tok] (BPState m il bl) m Tok
forall (m :: * -> *) s. Monad m => Char -> ParsecT [Tok] s m Tok
symbol '['
Bool
checked <- (Bool
False Bool
-> ParsecT [Tok] (BPState m il bl) m Tok
-> BlockParser m il bl Bool
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (Tok -> Bool) -> ParsecT [Tok] (BPState m il bl) m Tok
forall (m :: * -> *) s.
Monad m =>
(Tok -> Bool) -> ParsecT [Tok] s m Tok
satisfyTok (TokType -> Tok -> Bool
hasType TokType
Spaces))
BlockParser m il bl Bool
-> BlockParser m il bl Bool -> BlockParser m il bl Bool
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (Bool
True Bool
-> ParsecT [Tok] (BPState m il bl) m Tok
-> BlockParser m il bl Bool
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (Tok -> Bool) -> ParsecT [Tok] (BPState m il bl) m Tok
forall (m :: * -> *) s.
Monad m =>
(Tok -> Bool) -> ParsecT [Tok] s m Tok
satisfyTok ((Text -> Bool) -> Tok -> Bool
textIs (\t :: Text
t -> Text
t Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== "x" Bool -> Bool -> Bool
|| Text
t Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== "X")))
Char -> ParsecT [Tok] (BPState m il bl) m Tok
forall (m :: * -> *) s. Monad m => Char -> ParsecT [Tok] s m Tok
symbol ']'
Bool -> BlockParser m il bl Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
checked
class IsBlock il bl => HasTaskList il bl where
taskList :: ListType -> ListSpacing -> [(Bool, bl)] -> bl
instance Rangeable (Html a) => HasTaskList (Html a) (Html a) where
taskList :: ListType -> ListSpacing -> [(Bool, Html a)] -> Html a
taskList lt :: ListType
lt spacing :: ListSpacing
spacing items :: [(Bool, Html a)]
items =
Attribute -> Html a -> Html a
forall a. Attribute -> Html a -> Html a
addAttribute ("class","task-list")
(Html a -> Html a) -> Html a -> Html a
forall a b. (a -> b) -> a -> b
$ ListType -> ListSpacing -> [Html a] -> Html a
forall il b. IsBlock il b => ListType -> ListSpacing -> [b] -> b
list ListType
lt ListSpacing
spacing
([Html a] -> Html a) -> [Html a] -> Html a
forall a b. (a -> b) -> a -> b
$ ((Bool, Html a) -> Html a) -> [(Bool, Html a)] -> [Html a]
forall a b. (a -> b) -> [a] -> [b]
map (Bool, Html a) -> Html a
forall a. (Bool, Html a) -> Html a
addCheckbox [(Bool, Html a)]
items
addCheckbox :: (Bool, Html a) -> Html a
addCheckbox :: (Bool, Html a) -> Html a
addCheckbox (checked :: Bool
checked, x :: Html a
x) =
(Attribute -> Html a -> Html a
forall a. Attribute -> Html a -> Html a
addAttribute ("type", "checkbox") (Html a -> Html a) -> Html a -> Html a
forall a b. (a -> b) -> a -> b
$
Attribute -> Html a -> Html a
forall a. Attribute -> Html a -> Html a
addAttribute ("disabled", "") (Html a -> Html a) -> Html a -> Html a
forall a b. (a -> b) -> a -> b
$
(if Bool
checked then Attribute -> Html a -> Html a
forall a. Attribute -> Html a -> Html a
addAttribute ("checked","") else Html a -> Html a
forall a. a -> a
id) (Html a -> Html a) -> Html a -> Html a
forall a b. (a -> b) -> a -> b
$
Text -> Maybe (Html a) -> Html a
forall a. Text -> Maybe (Html a) -> Html a
htmlInline "input" Maybe (Html a)
forall a. Maybe a
Nothing) Html a -> Html a -> Html a
forall a. Semigroup a => a -> a -> a
<> Html a
x
instance (HasTaskList il bl, Semigroup bl, Semigroup il)
=> HasTaskList (WithSourceMap il) (WithSourceMap bl) where
taskList :: ListType
-> ListSpacing -> [(Bool, WithSourceMap bl)] -> WithSourceMap bl
taskList lt :: ListType
lt spacing :: ListSpacing
spacing items :: [(Bool, WithSourceMap bl)]
items =
(do let (checks :: [Bool]
checks, xs :: [WithSourceMap bl]
xs) = [(Bool, WithSourceMap bl)] -> ([Bool], [WithSourceMap bl])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Bool, WithSourceMap bl)]
items
ListType -> ListSpacing -> [(Bool, bl)] -> bl
forall il bl.
HasTaskList il bl =>
ListType -> ListSpacing -> [(Bool, bl)] -> bl
taskList ListType
lt ListSpacing
spacing ([(Bool, bl)] -> bl) -> ([bl] -> [(Bool, bl)]) -> [bl] -> bl
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Bool] -> [bl] -> [(Bool, bl)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Bool]
checks ([bl] -> bl) -> WithSourceMap [bl] -> WithSourceMap bl
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [WithSourceMap bl] -> WithSourceMap [bl]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [WithSourceMap bl]
xs
) WithSourceMap bl -> WithSourceMap () -> WithSourceMap bl
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Text -> WithSourceMap ()
addName "taskList"