{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Text.Pandoc.Chunks
( Chunk(..)
, ChunkedDoc(..)
, PathTemplate(..)
, splitIntoChunks
, toTOCTree
, tocToList
, SecInfo(..)
) where
import Text.Pandoc.Definition
import Text.Pandoc.Shared (makeSections, stringify, inlineListToIdentifier,
tshow, uniqueIdent)
import Text.Pandoc.Walk (Walkable(..), query)
import Data.Aeson (FromJSON, ToJSON)
import Data.Text (Text)
import Text.Printf (printf)
import Data.Maybe (fromMaybe, isNothing)
import qualified Data.Map as M
import qualified Data.Text as T
import Data.String (IsString)
import GHC.Generics (Generic)
import Text.HTML.TagSoup (Tag (TagOpen), fromAttrib, parseTags)
import Data.Tree (Tree(..))
import Data.Data (Data)
import Data.Typeable (Typeable)
import qualified Data.Set as Set
import Control.Monad.State
splitIntoChunks :: PathTemplate
-> Bool
-> Maybe Int
-> Int
-> Pandoc
-> ChunkedDoc
splitIntoChunks :: PathTemplate -> Bool -> Maybe Int -> Int -> Pandoc -> ChunkedDoc
splitIntoChunks PathTemplate
pathTemplate Bool
numberSections Maybe Int
mbBaseLevel
Int
chunklev (Pandoc Meta
meta [Block]
blocks) =
ChunkedDoc -> ChunkedDoc
addNav (ChunkedDoc -> ChunkedDoc)
-> (ChunkedDoc -> ChunkedDoc) -> ChunkedDoc -> ChunkedDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
ChunkedDoc -> ChunkedDoc
fixInternalReferences (ChunkedDoc -> ChunkedDoc)
-> (ChunkedDoc -> ChunkedDoc) -> ChunkedDoc -> ChunkedDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(Block -> Block) -> ChunkedDoc -> ChunkedDoc
forall a b. Walkable a b => (a -> a) -> b -> b
walk Block -> Block
rmNavAttrs (ChunkedDoc -> ChunkedDoc) -> ChunkedDoc -> ChunkedDoc
forall a b. (a -> b) -> a -> b
$
ChunkedDoc{ chunkedMeta :: Meta
chunkedMeta = Meta
meta
, chunkedChunks :: [Chunk]
chunkedChunks = [Chunk]
chunks
, chunkedTOC :: Tree SecInfo
chunkedTOC = Tree SecInfo
tocTree }
where
tocTree :: Tree SecInfo
tocTree = [Chunk] -> Tree SecInfo -> Tree SecInfo
fixTOCTreePaths [Chunk]
chunks (Tree SecInfo -> Tree SecInfo) -> Tree SecInfo -> Tree SecInfo
forall a b. (a -> b) -> a -> b
$ [Block] -> Tree SecInfo
toTOCTree [Block]
sections
chunks :: [Chunk]
chunks = Int -> PathTemplate -> Meta -> [Block] -> [Chunk]
makeChunks Int
chunklev PathTemplate
pathTemplate Meta
meta ([Block] -> [Chunk]) -> [Block] -> [Chunk]
forall a b. (a -> b) -> a -> b
$ [Block]
sections
sections :: [Block]
sections = [Block] -> [Block]
ensureIds ([Block] -> [Block]) -> [Block] -> [Block]
forall a b. (a -> b) -> a -> b
$ Bool -> Maybe Int -> [Block] -> [Block]
makeSections Bool
numberSections Maybe Int
mbBaseLevel [Block]
blocks
ensureIds :: [Block] -> [Block]
ensureIds :: [Block] -> [Block]
ensureIds [Block]
bs = State (Set Text) [Block] -> Set Text -> [Block]
forall s a. State s a -> s -> a
evalState ((Block -> StateT (Set Text) Identity Block)
-> [Block] -> State (Set Text) [Block]
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Block -> m Block) -> [Block] -> m [Block]
walkM Block -> StateT (Set Text) Identity Block
go [Block]
bs) Set Text
forall a. Monoid a => a
mempty
where
go :: Block -> State (Set.Set Text) Block
go :: Block -> StateT (Set Text) Identity Block
go b :: Block
b@(Div (Text
ident,Text
"section":[Text]
cls,[(Text, Text)]
kvs) bs' :: [Block]
bs'@(Header Int
_ (Text, [Text], [(Text, Text)])
_ [Inline]
ils : [Block]
_))
| Text -> Bool
T.null Text
ident
= do Set Text
ids <- StateT (Set Text) Identity (Set Text)
forall s (m :: * -> *). MonadState s m => m s
get
let newid :: Text
newid = Extensions -> [Inline] -> Set Text -> Text
uniqueIdent Extensions
forall a. Monoid a => a
mempty [Inline]
ils Set Text
ids
(Set Text -> Set Text) -> StateT (Set Text) Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Set Text -> Set Text) -> StateT (Set Text) Identity ())
-> (Set Text -> Set Text) -> StateT (Set Text) Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> Set Text -> Set Text
forall a. Ord a => a -> Set a -> Set a
Set.insert Text
newid
Block -> StateT (Set Text) Identity Block
forall a. a -> StateT (Set Text) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Block -> StateT (Set Text) Identity Block)
-> Block -> StateT (Set Text) Identity Block
forall a b. (a -> b) -> a -> b
$ (Text, [Text], [(Text, Text)]) -> [Block] -> Block
Div (Text
newid,Text
"section"Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:[Text]
cls,[(Text, Text)]
kvs) [Block]
bs'
| Bool
otherwise
= do (Set Text -> Set Text) -> StateT (Set Text) Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Set Text -> Set Text) -> StateT (Set Text) Identity ())
-> (Set Text -> Set Text) -> StateT (Set Text) Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> Set Text -> Set Text
forall a. Ord a => a -> Set a -> Set a
Set.insert Text
ident
Block -> StateT (Set Text) Identity Block
forall a. a -> StateT (Set Text) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Block
b
go Block
b = Block -> StateT (Set Text) Identity Block
forall a. a -> StateT (Set Text) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Block
b
addNav :: ChunkedDoc -> ChunkedDoc
addNav :: ChunkedDoc -> ChunkedDoc
addNav ChunkedDoc
chunkedDoc =
ChunkedDoc
chunkedDoc{ chunkedChunks =
addNext . addPrev . addUp $ chunkedChunks chunkedDoc }
addUp :: [Chunk] -> [Chunk]
addUp :: [Chunk] -> [Chunk]
addUp (Chunk
c : Chunk
d : [Chunk]
ds)
| Chunk -> Int
chunkLevel Chunk
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Chunk -> Int
chunkLevel Chunk
d
= Chunk
c Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
: [Chunk] -> [Chunk]
addUp (Chunk
d{ chunkUp = Just c } Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
: [Chunk]
ds)
| Chunk -> Int
chunkLevel Chunk
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Chunk -> Int
chunkLevel Chunk
d
= Chunk
c Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
: [Chunk] -> [Chunk]
addUp (Chunk
d{ chunkUp = chunkUp c} Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
: [Chunk]
ds)
addUp (Chunk
c:[Chunk]
cs) = Chunk
c Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
: [Chunk] -> [Chunk]
addUp [Chunk]
cs
addUp [] = []
addNext :: [Chunk] -> [Chunk]
addNext :: [Chunk] -> [Chunk]
addNext [Chunk]
cs = (Chunk -> Maybe Chunk -> Chunk)
-> [Chunk] -> [Maybe Chunk] -> [Chunk]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Chunk -> Maybe Chunk -> Chunk
go [Chunk]
cs ((Chunk -> Maybe Chunk) -> [Chunk] -> [Maybe Chunk]
forall a b. (a -> b) -> [a] -> [b]
map Chunk -> Maybe Chunk
forall a. a -> Maybe a
Just ([Chunk] -> [Chunk]
forall a. HasCallStack => [a] -> [a]
tail [Chunk]
cs) [Maybe Chunk] -> [Maybe Chunk] -> [Maybe Chunk]
forall a. [a] -> [a] -> [a]
++ [Maybe Chunk
forall a. Maybe a
Nothing])
where
go :: Chunk -> Maybe Chunk -> Chunk
go Chunk
c Maybe Chunk
nxt = Chunk
c{ chunkNext = nxt }
addPrev :: [Chunk] -> [Chunk]
addPrev :: [Chunk] -> [Chunk]
addPrev [Chunk]
cs = (Chunk -> Maybe Chunk -> Chunk)
-> [Chunk] -> [Maybe Chunk] -> [Chunk]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Chunk -> Maybe Chunk -> Chunk
go [Chunk]
cs (Maybe Chunk
forall a. Maybe a
Nothing Maybe Chunk -> [Maybe Chunk] -> [Maybe Chunk]
forall a. a -> [a] -> [a]
: (Chunk -> Maybe Chunk) -> [Chunk] -> [Maybe Chunk]
forall a b. (a -> b) -> [a] -> [b]
map Chunk -> Maybe Chunk
forall a. a -> Maybe a
Just [Chunk]
cs)
where
go :: Chunk -> Maybe Chunk -> Chunk
go Chunk
c Maybe Chunk
prev = Chunk
c{ chunkPrev = prev }
fixInternalReferences :: ChunkedDoc -> ChunkedDoc
fixInternalReferences :: ChunkedDoc -> ChunkedDoc
fixInternalReferences ChunkedDoc
chunkedDoc = (Inline -> Inline) -> ChunkedDoc -> ChunkedDoc
forall a b. Walkable a b => (a -> a) -> b -> b
walk Inline -> Inline
fixInternalRefs ChunkedDoc
chunkedDoc
where
fixInternalRefs :: Inline -> Inline
fixInternalRefs :: Inline -> Inline
fixInternalRefs il :: Inline
il@(Link (Text, [Text], [(Text, Text)])
attr [Inline]
ils (Text
src,Text
tit))
= case Text -> Maybe (Char, Text)
T.uncons Text
src of
Just (Char
'#', Text
ident) -> (Text, [Text], [(Text, Text)])
-> [Inline] -> (Text, Text) -> Inline
Link (Text, [Text], [(Text, Text)])
attr [Inline]
ils (Text
src', Text
tit)
where src' :: Text
src' = case Text -> Map Text Chunk -> Maybe Chunk
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Text
ident Map Text Chunk
refMap of
Just Chunk
chunk -> String -> Text
T.pack (Chunk -> String
chunkPath Chunk
chunk) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
src
Maybe Chunk
Nothing -> Text
src
Maybe (Char, Text)
_ -> Inline
il
fixInternalRefs Inline
il = Inline
il
refMap :: Map Text Chunk
refMap = (Chunk -> Map Text Chunk -> Map Text Chunk)
-> Map Text Chunk -> [Chunk] -> Map Text Chunk
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Chunk -> Map Text Chunk -> Map Text Chunk
chunkToRefs Map Text Chunk
forall a. Monoid a => a
mempty (ChunkedDoc -> [Chunk]
chunkedChunks ChunkedDoc
chunkedDoc)
chunkToRefs :: Chunk -> Map Text Chunk -> Map Text Chunk
chunkToRefs Chunk
chunk Map Text Chunk
m =
let idents :: [Text]
idents = Chunk -> Text
chunkId Chunk
chunk Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Block] -> [Text]
forall {b}. (Walkable Block b, Walkable Inline b) => b -> [Text]
getIdents (Chunk -> [Block]
chunkContents Chunk
chunk)
in (Text -> Map Text Chunk -> Map Text Chunk)
-> Map Text Chunk -> [Text] -> Map Text Chunk
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Text
ident -> Text -> Chunk -> Map Text Chunk -> Map Text Chunk
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
ident Chunk
chunk) Map Text Chunk
m [Text]
idents
getIdents :: b -> [Text]
getIdents b
bs = (Block -> [Text]) -> b -> [Text]
forall c. Monoid c => (Block -> c) -> b -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Block -> [Text]
getBlockIdent b
bs [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (Inline -> [Text]) -> b -> [Text]
forall c. Monoid c => (Inline -> c) -> b -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Inline -> [Text]
getInlineIdent b
bs
getBlockIdent :: Block -> [Text]
getBlockIdent :: Block -> [Text]
getBlockIdent (Div (Text
ident, [Text]
_, [(Text, Text)]
_) [Block]
_)
| Bool -> Bool
not (Text -> Bool
T.null Text
ident) = [Text
ident]
getBlockIdent (Header Int
_ (Text
ident, [Text]
_, [(Text, Text)]
_) [Inline]
_)
| Bool -> Bool
not (Text -> Bool
T.null Text
ident) = [Text
ident]
getBlockIdent (Table (Text
ident,[Text]
_,[(Text, Text)]
_) Caption
_ [ColSpec]
_ TableHead
_ [TableBody]
_ TableFoot
_)
| Bool -> Bool
not (Text -> Bool
T.null Text
ident) = [Text
ident]
getBlockIdent (RawBlock Format
fmt Text
raw)
| Format -> Bool
isHtmlFormat Format
fmt
= (Tag Text -> [Text] -> [Text]) -> [Text] -> [Tag Text] -> [Text]
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Tag Text
tag ->
case Tag Text
tag of
TagOpen{} ->
case Text -> Tag Text -> Text
forall str.
(Show str, Eq str, StringLike str) =>
str -> Tag str -> str
fromAttrib Text
"id" Tag Text
tag of
Text
"" -> [Text] -> [Text]
forall a. a -> a
id
Text
x -> (Text
xText -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:)
Tag Text
_ -> [Text] -> [Text]
forall a. a -> a
id)
[] (Text -> [Tag Text]
forall str. StringLike str => str -> [Tag str]
parseTags Text
raw)
getBlockIdent Block
_ = []
getInlineIdent :: Inline -> [Text]
getInlineIdent :: Inline -> [Text]
getInlineIdent (Span (Text
ident, [Text]
_, [(Text, Text)]
_) [Inline]
_)
| Bool -> Bool
not (Text -> Bool
T.null Text
ident) = [Text
ident]
getInlineIdent (Link (Text
ident, [Text]
_, [(Text, Text)]
_) [Inline]
_ (Text, Text)
_)
| Bool -> Bool
not (Text -> Bool
T.null Text
ident) = [Text
ident]
getInlineIdent (Image (Text
ident, [Text]
_, [(Text, Text)]
_) [Inline]
_ (Text, Text)
_)
| Bool -> Bool
not (Text -> Bool
T.null Text
ident) = [Text
ident]
getInlineIdent (RawInline Format
fmt Text
raw)
| Format -> Bool
isHtmlFormat Format
fmt
= (Tag Text -> [Text] -> [Text]) -> [Text] -> [Tag Text] -> [Text]
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Tag Text
tag ->
case Tag Text
tag of
TagOpen{} ->
case Text -> Tag Text -> Text
forall str.
(Show str, Eq str, StringLike str) =>
str -> Tag str -> str
fromAttrib Text
"id" Tag Text
tag of
Text
"" -> [Text] -> [Text]
forall a. a -> a
id
Text
x -> (Text
xText -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:)
Tag Text
_ -> [Text] -> [Text]
forall a. a -> a
id)
[] (Text -> [Tag Text]
forall str. StringLike str => str -> [Tag str]
parseTags Text
raw)
getInlineIdent Inline
_ = []
isHtmlFormat :: Format -> Bool
isHtmlFormat :: Format -> Bool
isHtmlFormat (Format Text
"html") = Bool
True
isHtmlFormat (Format Text
"html4") = Bool
True
isHtmlFormat (Format Text
"html5") = Bool
True
isHtmlFormat Format
_ = Bool
False
makeChunks :: Int -> PathTemplate -> Meta -> [Block] -> [Chunk]
makeChunks :: Int -> PathTemplate -> Meta -> [Block] -> [Chunk]
makeChunks Int
chunklev PathTemplate
pathTemplate Meta
meta = Int -> [Block] -> [Chunk]
secsToChunks Int
1
where
isChunkHeader :: Block -> Bool
isChunkHeader :: Block -> Bool
isChunkHeader (Div (Text
_,Text
"section":[Text]
_,[(Text, Text)]
_) (Header Int
n (Text, [Text], [(Text, Text)])
_ [Inline]
_:[Block]
_)) = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
chunklev
isChunkHeader Block
_ = Bool
False
secsToChunks :: Int -> [Block] -> [Chunk]
secsToChunks :: Int -> [Block] -> [Chunk]
secsToChunks Int
chunknum [Block]
bs =
case (Block -> Bool) -> [Block] -> ([Block], [Block])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break Block -> Bool
isChunkHeader [Block]
bs of
([], []) -> []
([], (d :: Block
d@(Div attr :: (Text, [Text], [(Text, Text)])
attr@(Text
_,Text
"section":[Text]
_,[(Text, Text)]
_) (h :: Block
h@(Header Int
lvl (Text, [Text], [(Text, Text)])
_ [Inline]
_) : [Block]
bs')) : [Block]
rest))
| Int
chunklev Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
lvl ->
Int -> Block -> Chunk
toChunk Int
chunknum Block
d Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
:
Int -> [Block] -> [Chunk]
secsToChunks (Int
chunknum Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Block]
rest
| Int
chunklev Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
lvl ->
case (Block -> Bool) -> [Block] -> ([Block], [Block])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break Block -> Bool
isChunkHeader [Block]
bs' of
([Block]
xs, [Block]
ys) -> Int -> Block -> Chunk
toChunk Int
chunknum ((Text, [Text], [(Text, Text)]) -> [Block] -> Block
Div (Text, [Text], [(Text, Text)])
attr (Block
hBlock -> [Block] -> [Block]
forall a. a -> [a] -> [a]
:[Block]
xs)) Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
:
Int -> [Block] -> [Chunk]
secsToChunks (Int
chunknum Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) ([Block]
ys [Block] -> [Block] -> [Block]
forall a. [a] -> [a] -> [a]
++ [Block]
rest)
([Block]
xs, [Block]
ys) -> Int -> Block -> Chunk
toChunk Int
chunknum
((Text, [Text], [(Text, Text)]) -> [Block] -> Block
Div (Text
"",[Text
"preamble"],[]) [Block]
xs) Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
:
Int -> [Block] -> [Chunk]
secsToChunks (Int
chunknum Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Block]
ys
toChunk :: Int -> Block -> Chunk
toChunk :: Int -> Block -> Chunk
toChunk Int
chunknum
(Div (Text
divid,Text
"section":[Text]
classes,[(Text, Text)]
kvs) (h :: Block
h@(Header Int
lvl (Text, [Text], [(Text, Text)])
_ [Inline]
ils) : [Block]
bs)) =
Chunk
{ chunkHeading :: [Inline]
chunkHeading = [Inline]
ils
, chunkId :: Text
chunkId = Text
divid
, chunkLevel :: Int
chunkLevel = Int
lvl
, chunkNumber :: Int
chunkNumber = Int
chunknum
, chunkSectionNumber :: Maybe Text
chunkSectionNumber = Maybe Text
secnum
, chunkPath :: String
chunkPath = String
chunkpath
, chunkUp :: Maybe Chunk
chunkUp = Maybe Chunk
forall a. Maybe a
Nothing
, chunkNext :: Maybe Chunk
chunkNext = Maybe Chunk
forall a. Maybe a
Nothing
, chunkPrev :: Maybe Chunk
chunkPrev = Maybe Chunk
forall a. Maybe a
Nothing
, chunkUnlisted :: Bool
chunkUnlisted = Text
"unlisted" Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
classes
, chunkContents :: [Block]
chunkContents =
[(Text, [Text], [(Text, Text)]) -> [Block] -> Block
Div (Text
divid,Text
"section"Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:[Text]
classes,[(Text, Text)]
kvs') (Block
h Block -> [Block] -> [Block]
forall a. a -> [a] -> [a]
: [Block]
bs)]
}
where kvs' :: [(Text, Text)]
kvs' = [(Text, Text)]
kvs [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
forall a. [a] -> [a] -> [a]
++ [(Text
"nav-path", String -> Text
T.pack String
chunkpath)]
secnum :: Maybe Text
secnum = Text -> [(Text, Text)] -> Maybe Text
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
"number" [(Text, Text)]
kvs
chunkpath :: String
chunkpath = PathTemplate -> Int -> Text -> Text -> Text -> String
resolvePathTemplate PathTemplate
pathTemplate Int
chunknum
([Inline] -> Text
forall a. Walkable Inline a => a -> Text
stringify [Inline]
ils)
Text
divid
(Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" Maybe Text
secnum)
toChunk Int
chunknum (Div (Text
"",[Text
"preamble"],[]) [Block]
bs) =
Chunk
{ chunkHeading :: [Inline]
chunkHeading = Meta -> [Inline]
docTitle Meta
meta
, chunkId :: Text
chunkId = Text
chunkid
, chunkLevel :: Int
chunkLevel = Int
0
, chunkNumber :: Int
chunkNumber = Int
chunknum
, chunkSectionNumber :: Maybe Text
chunkSectionNumber = Maybe Text
forall a. Maybe a
Nothing
, chunkPath :: String
chunkPath = String
chunkpath
, chunkUp :: Maybe Chunk
chunkUp = Maybe Chunk
forall a. Maybe a
Nothing
, chunkPrev :: Maybe Chunk
chunkPrev = Maybe Chunk
forall a. Maybe a
Nothing
, chunkNext :: Maybe Chunk
chunkNext = Maybe Chunk
forall a. Maybe a
Nothing
, chunkUnlisted :: Bool
chunkUnlisted = Bool
False
, chunkContents :: [Block]
chunkContents = [Block]
bs
}
where
chunkpath :: String
chunkpath = PathTemplate -> Int -> Text -> Text -> Text -> String
resolvePathTemplate PathTemplate
pathTemplate Int
chunknum
([Inline] -> Text
forall a. Walkable Inline a => a -> Text
stringify (Meta -> [Inline]
docTitle Meta
meta))
Text
chunkid
Text
"0"
chunkid :: Text
chunkid = Extensions -> [Inline] -> Text
inlineListToIdentifier Extensions
forall a. Monoid a => a
mempty (Meta -> [Inline]
docTitle Meta
meta) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
"-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
chunknum
toChunk Int
_ Block
b = String -> Chunk
forall a. HasCallStack => String -> a
error (String -> Chunk) -> String -> Chunk
forall a b. (a -> b) -> a -> b
$ String
"toChunk called on inappropriate block " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Block -> String
forall a. Show a => a -> String
show Block
b
rmNavAttrs :: Block -> Block
rmNavAttrs :: Block -> Block
rmNavAttrs (Div (Text
ident,[Text]
classes,[(Text, Text)]
kvs) [Block]
bs) =
(Text, [Text], [(Text, Text)]) -> [Block] -> Block
Div (Text
ident,[Text]
classes,((Text, Text) -> Bool) -> [(Text, Text)] -> [(Text, Text)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> ((Text, Text) -> Bool) -> (Text, Text) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, Text) -> Bool
forall {b}. (Text, b) -> Bool
isNavAttr) [(Text, Text)]
kvs) [Block]
bs
where
isNavAttr :: (Text, b) -> Bool
isNavAttr (Text
k,b
_) = Text
"nav-" Text -> Text -> Bool
`T.isPrefixOf` Text
k
rmNavAttrs Block
b = Block
b
resolvePathTemplate :: PathTemplate
-> Int
-> Text
-> Text
-> Text
-> FilePath
resolvePathTemplate :: PathTemplate -> Int -> Text -> Text -> Text -> String
resolvePathTemplate (PathTemplate Text
templ) Int
chunknum Text
headingText Text
ident Text
secnum =
Text -> String
T.unpack (Text -> String) -> (Text -> Text) -> Text -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(Char -> Bool) -> Text -> Text
T.filter (\Char
c -> Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\\') (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
"%n" (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String -> Int -> String
forall r. PrintfType r => String -> r
printf String
"%03d" Int
chunknum) (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
"%s" Text
secnum (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
"%h" Text
headingText (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
"%i" Text
ident (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$
Text
templ
newtype PathTemplate =
PathTemplate { PathTemplate -> Text
unPathTemplate :: Text }
deriving (Int -> PathTemplate -> String -> String
[PathTemplate] -> String -> String
PathTemplate -> String
(Int -> PathTemplate -> String -> String)
-> (PathTemplate -> String)
-> ([PathTemplate] -> String -> String)
-> Show PathTemplate
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> PathTemplate -> String -> String
showsPrec :: Int -> PathTemplate -> String -> String
$cshow :: PathTemplate -> String
show :: PathTemplate -> String
$cshowList :: [PathTemplate] -> String -> String
showList :: [PathTemplate] -> String -> String
Show, String -> PathTemplate
(String -> PathTemplate) -> IsString PathTemplate
forall a. (String -> a) -> IsString a
$cfromString :: String -> PathTemplate
fromString :: String -> PathTemplate
IsString, Typeable PathTemplate
Typeable PathTemplate =>
(forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PathTemplate -> c PathTemplate)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PathTemplate)
-> (PathTemplate -> Constr)
-> (PathTemplate -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PathTemplate))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c PathTemplate))
-> ((forall b. Data b => b -> b) -> PathTemplate -> PathTemplate)
-> (forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r)
-> (forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r)
-> (forall u. (forall d. Data d => d -> u) -> PathTemplate -> [u])
-> (forall u.
Int -> (forall d. Data d => d -> u) -> PathTemplate -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate)
-> Data PathTemplate
PathTemplate -> Constr
PathTemplate -> DataType
(forall b. Data b => b -> b) -> PathTemplate -> PathTemplate
forall a.
Typeable a =>
(forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> PathTemplate -> u
forall u. (forall d. Data d => d -> u) -> PathTemplate -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PathTemplate
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PathTemplate -> c PathTemplate
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PathTemplate)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c PathTemplate)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PathTemplate -> c PathTemplate
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PathTemplate -> c PathTemplate
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PathTemplate
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PathTemplate
$ctoConstr :: PathTemplate -> Constr
toConstr :: PathTemplate -> Constr
$cdataTypeOf :: PathTemplate -> DataType
dataTypeOf :: PathTemplate -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PathTemplate)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PathTemplate)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c PathTemplate)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c PathTemplate)
$cgmapT :: (forall b. Data b => b -> b) -> PathTemplate -> PathTemplate
gmapT :: (forall b. Data b => b -> b) -> PathTemplate -> PathTemplate
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PathTemplate -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> PathTemplate -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> PathTemplate -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PathTemplate -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PathTemplate -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PathTemplate -> m PathTemplate
Data, Typeable, (forall x. PathTemplate -> Rep PathTemplate x)
-> (forall x. Rep PathTemplate x -> PathTemplate)
-> Generic PathTemplate
forall x. Rep PathTemplate x -> PathTemplate
forall x. PathTemplate -> Rep PathTemplate x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PathTemplate -> Rep PathTemplate x
from :: forall x. PathTemplate -> Rep PathTemplate x
$cto :: forall x. Rep PathTemplate x -> PathTemplate
to :: forall x. Rep PathTemplate x -> PathTemplate
Generic, [PathTemplate] -> Value
[PathTemplate] -> Encoding
PathTemplate -> Bool
PathTemplate -> Value
PathTemplate -> Encoding
(PathTemplate -> Value)
-> (PathTemplate -> Encoding)
-> ([PathTemplate] -> Value)
-> ([PathTemplate] -> Encoding)
-> (PathTemplate -> Bool)
-> ToJSON PathTemplate
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: PathTemplate -> Value
toJSON :: PathTemplate -> Value
$ctoEncoding :: PathTemplate -> Encoding
toEncoding :: PathTemplate -> Encoding
$ctoJSONList :: [PathTemplate] -> Value
toJSONList :: [PathTemplate] -> Value
$ctoEncodingList :: [PathTemplate] -> Encoding
toEncodingList :: [PathTemplate] -> Encoding
$comitField :: PathTemplate -> Bool
omitField :: PathTemplate -> Bool
ToJSON, Maybe PathTemplate
Value -> Parser [PathTemplate]
Value -> Parser PathTemplate
(Value -> Parser PathTemplate)
-> (Value -> Parser [PathTemplate])
-> Maybe PathTemplate
-> FromJSON PathTemplate
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser PathTemplate
parseJSON :: Value -> Parser PathTemplate
$cparseJSONList :: Value -> Parser [PathTemplate]
parseJSONList :: Value -> Parser [PathTemplate]
$comittedField :: Maybe PathTemplate
omittedField :: Maybe PathTemplate
FromJSON)
data Chunk =
Chunk
{ Chunk -> [Inline]
chunkHeading :: [Inline]
, Chunk -> Text
chunkId :: Text
, Chunk -> Int
chunkLevel :: Int
, Chunk -> Int
chunkNumber :: Int
, Chunk -> Maybe Text
chunkSectionNumber :: Maybe Text
, Chunk -> String
chunkPath :: FilePath
, Chunk -> Maybe Chunk
chunkUp :: Maybe Chunk
, Chunk -> Maybe Chunk
chunkPrev :: Maybe Chunk
, Chunk -> Maybe Chunk
chunkNext :: Maybe Chunk
, Chunk -> Bool
chunkUnlisted :: Bool
, Chunk -> [Block]
chunkContents :: [Block]
}
deriving (Int -> Chunk -> String -> String
[Chunk] -> String -> String
Chunk -> String
(Int -> Chunk -> String -> String)
-> (Chunk -> String) -> ([Chunk] -> String -> String) -> Show Chunk
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Chunk -> String -> String
showsPrec :: Int -> Chunk -> String -> String
$cshow :: Chunk -> String
show :: Chunk -> String
$cshowList :: [Chunk] -> String -> String
showList :: [Chunk] -> String -> String
Show, Chunk -> Chunk -> Bool
(Chunk -> Chunk -> Bool) -> (Chunk -> Chunk -> Bool) -> Eq Chunk
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Chunk -> Chunk -> Bool
== :: Chunk -> Chunk -> Bool
$c/= :: Chunk -> Chunk -> Bool
/= :: Chunk -> Chunk -> Bool
Eq, (forall x. Chunk -> Rep Chunk x)
-> (forall x. Rep Chunk x -> Chunk) -> Generic Chunk
forall x. Rep Chunk x -> Chunk
forall x. Chunk -> Rep Chunk x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Chunk -> Rep Chunk x
from :: forall x. Chunk -> Rep Chunk x
$cto :: forall x. Rep Chunk x -> Chunk
to :: forall x. Rep Chunk x -> Chunk
Generic)
instance Walkable Inline Chunk where
query :: forall c. Monoid c => (Inline -> c) -> Chunk -> c
query Inline -> c
f Chunk
chunk = (Inline -> c) -> [Block] -> c
forall c. Monoid c => (Inline -> c) -> [Block] -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Inline -> c
f (Chunk -> [Block]
chunkContents Chunk
chunk)
walk :: (Inline -> Inline) -> Chunk -> Chunk
walk Inline -> Inline
f Chunk
chunk = Chunk
chunk{ chunkContents = walk f (chunkContents chunk) }
walkM :: forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Inline -> m Inline) -> Chunk -> m Chunk
walkM Inline -> m Inline
f Chunk
chunk = do
[Block]
contents <- (Inline -> m Inline) -> [Block] -> m [Block]
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Inline -> m Inline) -> [Block] -> m [Block]
walkM Inline -> m Inline
f (Chunk -> [Block]
chunkContents Chunk
chunk)
Chunk -> m Chunk
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Chunk
chunk{ chunkContents = contents }
instance Walkable Block Chunk where
query :: forall c. Monoid c => (Block -> c) -> Chunk -> c
query Block -> c
f Chunk
chunk = (Block -> c) -> [Block] -> c
forall c. Monoid c => (Block -> c) -> [Block] -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Block -> c
f (Chunk -> [Block]
chunkContents Chunk
chunk)
walk :: (Block -> Block) -> Chunk -> Chunk
walk Block -> Block
f Chunk
chunk = Chunk
chunk{ chunkContents = walk f (chunkContents chunk) }
walkM :: forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Block -> m Block) -> Chunk -> m Chunk
walkM Block -> m Block
f Chunk
chunk = do
[Block]
contents <- (Block -> m Block) -> [Block] -> m [Block]
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Block -> m Block) -> [Block] -> m [Block]
walkM Block -> m Block
f (Chunk -> [Block]
chunkContents Chunk
chunk)
Chunk -> m Chunk
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Chunk
chunk{ chunkContents = contents }
data ChunkedDoc =
ChunkedDoc
{ ChunkedDoc -> Meta
chunkedMeta :: Meta
, ChunkedDoc -> Tree SecInfo
chunkedTOC :: Tree SecInfo
, ChunkedDoc -> [Chunk]
chunkedChunks :: [Chunk]
} deriving (Int -> ChunkedDoc -> String -> String
[ChunkedDoc] -> String -> String
ChunkedDoc -> String
(Int -> ChunkedDoc -> String -> String)
-> (ChunkedDoc -> String)
-> ([ChunkedDoc] -> String -> String)
-> Show ChunkedDoc
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> ChunkedDoc -> String -> String
showsPrec :: Int -> ChunkedDoc -> String -> String
$cshow :: ChunkedDoc -> String
show :: ChunkedDoc -> String
$cshowList :: [ChunkedDoc] -> String -> String
showList :: [ChunkedDoc] -> String -> String
Show, ChunkedDoc -> ChunkedDoc -> Bool
(ChunkedDoc -> ChunkedDoc -> Bool)
-> (ChunkedDoc -> ChunkedDoc -> Bool) -> Eq ChunkedDoc
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ChunkedDoc -> ChunkedDoc -> Bool
== :: ChunkedDoc -> ChunkedDoc -> Bool
$c/= :: ChunkedDoc -> ChunkedDoc -> Bool
/= :: ChunkedDoc -> ChunkedDoc -> Bool
Eq, (forall x. ChunkedDoc -> Rep ChunkedDoc x)
-> (forall x. Rep ChunkedDoc x -> ChunkedDoc) -> Generic ChunkedDoc
forall x. Rep ChunkedDoc x -> ChunkedDoc
forall x. ChunkedDoc -> Rep ChunkedDoc x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ChunkedDoc -> Rep ChunkedDoc x
from :: forall x. ChunkedDoc -> Rep ChunkedDoc x
$cto :: forall x. Rep ChunkedDoc x -> ChunkedDoc
to :: forall x. Rep ChunkedDoc x -> ChunkedDoc
Generic)
instance Walkable Inline ChunkedDoc where
query :: forall c. Monoid c => (Inline -> c) -> ChunkedDoc -> c
query Inline -> c
f ChunkedDoc
doc = (Inline -> c) -> [Chunk] -> c
forall c. Monoid c => (Inline -> c) -> [Chunk] -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Inline -> c
f (ChunkedDoc -> [Chunk]
chunkedChunks ChunkedDoc
doc) c -> c -> c
forall a. Semigroup a => a -> a -> a
<> (Inline -> c) -> Meta -> c
forall c. Monoid c => (Inline -> c) -> Meta -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Inline -> c
f (ChunkedDoc -> Meta
chunkedMeta ChunkedDoc
doc)
walk :: (Inline -> Inline) -> ChunkedDoc -> ChunkedDoc
walk Inline -> Inline
f ChunkedDoc
doc = ChunkedDoc
doc{ chunkedMeta = walk f (chunkedMeta doc)
, chunkedChunks = walk f (chunkedChunks doc)
}
walkM :: forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Inline -> m Inline) -> ChunkedDoc -> m ChunkedDoc
walkM Inline -> m Inline
f ChunkedDoc
doc = do
Meta
meta' <- (Inline -> m Inline) -> Meta -> m Meta
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Inline -> m Inline) -> Meta -> m Meta
walkM Inline -> m Inline
f (ChunkedDoc -> Meta
chunkedMeta ChunkedDoc
doc)
[Chunk]
chunks' <- (Inline -> m Inline) -> [Chunk] -> m [Chunk]
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Inline -> m Inline) -> [Chunk] -> m [Chunk]
walkM Inline -> m Inline
f (ChunkedDoc -> [Chunk]
chunkedChunks ChunkedDoc
doc)
ChunkedDoc -> m ChunkedDoc
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ChunkedDoc -> m ChunkedDoc) -> ChunkedDoc -> m ChunkedDoc
forall a b. (a -> b) -> a -> b
$ ChunkedDoc
doc{ chunkedMeta = meta'
, chunkedChunks = chunks' }
instance Walkable Block ChunkedDoc where
query :: forall c. Monoid c => (Block -> c) -> ChunkedDoc -> c
query Block -> c
f ChunkedDoc
doc = (Block -> c) -> [Chunk] -> c
forall c. Monoid c => (Block -> c) -> [Chunk] -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Block -> c
f (ChunkedDoc -> [Chunk]
chunkedChunks ChunkedDoc
doc) c -> c -> c
forall a. Semigroup a => a -> a -> a
<> (Block -> c) -> Meta -> c
forall c. Monoid c => (Block -> c) -> Meta -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Block -> c
f (ChunkedDoc -> Meta
chunkedMeta ChunkedDoc
doc)
walk :: (Block -> Block) -> ChunkedDoc -> ChunkedDoc
walk Block -> Block
f ChunkedDoc
doc = ChunkedDoc
doc{ chunkedMeta = walk f (chunkedMeta doc)
, chunkedChunks = walk f (chunkedChunks doc)
}
walkM :: forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Block -> m Block) -> ChunkedDoc -> m ChunkedDoc
walkM Block -> m Block
f ChunkedDoc
doc = do
Meta
meta' <- (Block -> m Block) -> Meta -> m Meta
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Block -> m Block) -> Meta -> m Meta
walkM Block -> m Block
f (ChunkedDoc -> Meta
chunkedMeta ChunkedDoc
doc)
[Chunk]
chunks' <- (Block -> m Block) -> [Chunk] -> m [Chunk]
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Block -> m Block) -> [Chunk] -> m [Chunk]
walkM Block -> m Block
f (ChunkedDoc -> [Chunk]
chunkedChunks ChunkedDoc
doc)
ChunkedDoc -> m ChunkedDoc
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ChunkedDoc -> m ChunkedDoc) -> ChunkedDoc -> m ChunkedDoc
forall a b. (a -> b) -> a -> b
$ ChunkedDoc
doc{ chunkedMeta = meta'
, chunkedChunks = chunks' }
data SecInfo =
SecInfo
{ SecInfo -> [Inline]
secTitle :: [Inline]
, SecInfo -> Maybe Text
secNumber :: Maybe Text
, SecInfo -> Text
secId :: Text
, SecInfo -> Text
secPath :: Text
, SecInfo -> Int
secLevel :: Int
} deriving (Int -> SecInfo -> String -> String
[SecInfo] -> String -> String
SecInfo -> String
(Int -> SecInfo -> String -> String)
-> (SecInfo -> String)
-> ([SecInfo] -> String -> String)
-> Show SecInfo
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> SecInfo -> String -> String
showsPrec :: Int -> SecInfo -> String -> String
$cshow :: SecInfo -> String
show :: SecInfo -> String
$cshowList :: [SecInfo] -> String -> String
showList :: [SecInfo] -> String -> String
Show, SecInfo -> SecInfo -> Bool
(SecInfo -> SecInfo -> Bool)
-> (SecInfo -> SecInfo -> Bool) -> Eq SecInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SecInfo -> SecInfo -> Bool
== :: SecInfo -> SecInfo -> Bool
$c/= :: SecInfo -> SecInfo -> Bool
/= :: SecInfo -> SecInfo -> Bool
Eq, (forall x. SecInfo -> Rep SecInfo x)
-> (forall x. Rep SecInfo x -> SecInfo) -> Generic SecInfo
forall x. Rep SecInfo x -> SecInfo
forall x. SecInfo -> Rep SecInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SecInfo -> Rep SecInfo x
from :: forall x. SecInfo -> Rep SecInfo x
$cto :: forall x. Rep SecInfo x -> SecInfo
to :: forall x. Rep SecInfo x -> SecInfo
Generic)
instance Walkable Inline SecInfo where
query :: forall c. Monoid c => (Inline -> c) -> SecInfo -> c
query Inline -> c
f SecInfo
sec = (Inline -> c) -> [Inline] -> c
forall c. Monoid c => (Inline -> c) -> [Inline] -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Inline -> c
f (SecInfo -> [Inline]
secTitle SecInfo
sec)
walk :: (Inline -> Inline) -> SecInfo -> SecInfo
walk Inline -> Inline
f SecInfo
sec = SecInfo
sec{ secTitle = walk f (secTitle sec) }
walkM :: forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Inline -> m Inline) -> SecInfo -> m SecInfo
walkM Inline -> m Inline
f SecInfo
sec = do
[Inline]
st <- (Inline -> m Inline) -> [Inline] -> m [Inline]
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
forall (m :: * -> *).
(Monad m, Applicative m, Functor m) =>
(Inline -> m Inline) -> [Inline] -> m [Inline]
walkM Inline -> m Inline
f (SecInfo -> [Inline]
secTitle SecInfo
sec)
SecInfo -> m SecInfo
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return SecInfo
sec{ secTitle = st }
toTOCTree :: [Block] -> Tree SecInfo
toTOCTree :: [Block] -> Tree SecInfo
toTOCTree =
SecInfo -> [Tree SecInfo] -> Tree SecInfo
forall a. a -> [Tree a] -> Tree a
Node SecInfo{ secTitle :: [Inline]
secTitle = []
, secNumber :: Maybe Text
secNumber = Maybe Text
forall a. Maybe a
Nothing
, secId :: Text
secId = Text
""
, secPath :: Text
secPath = Text
""
, secLevel :: Int
secLevel = Int
0 } ([Tree SecInfo] -> Tree SecInfo)
-> ([Block] -> [Tree SecInfo]) -> [Block] -> Tree SecInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Block -> [Tree SecInfo] -> [Tree SecInfo])
-> [Tree SecInfo] -> [Block] -> [Tree SecInfo]
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Block -> [Tree SecInfo] -> [Tree SecInfo]
go []
where
go :: Block -> [Tree SecInfo] -> [Tree SecInfo]
go :: Block -> [Tree SecInfo] -> [Tree SecInfo]
go (Div (Text
ident,[Text]
_,[(Text, Text)]
_) (Header Int
lev (Text
_,[Text]
classes,[(Text, Text)]
kvs) [Inline]
ils : [Block]
subsecs))
| Bool -> Bool
not (Maybe Text -> Bool
forall a. Maybe a -> Bool
isNothing (Text -> [(Text, Text)] -> Maybe Text
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
"number" [(Text, Text)]
kvs) Bool -> Bool -> Bool
&& Text
"unlisted" Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
classes)
= ((SecInfo -> [Tree SecInfo] -> Tree SecInfo
forall a. a -> [Tree a] -> Tree a
Node SecInfo{ secTitle :: [Inline]
secTitle = [Inline]
ils
, secNumber :: Maybe Text
secNumber = Text -> [(Text, Text)] -> Maybe Text
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
"number" [(Text, Text)]
kvs
, secId :: Text
secId = Text
ident
, secPath :: Text
secPath = Text
""
, secLevel :: Int
secLevel = Int
lev } ((Block -> [Tree SecInfo] -> [Tree SecInfo])
-> [Tree SecInfo] -> [Block] -> [Tree SecInfo]
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Block -> [Tree SecInfo] -> [Tree SecInfo]
go [] [Block]
subsecs)) Tree SecInfo -> [Tree SecInfo] -> [Tree SecInfo]
forall a. a -> [a] -> [a]
:)
go (Div (Text, [Text], [(Text, Text)])
_ [d :: Block
d@Div{}]) = Block -> [Tree SecInfo] -> [Tree SecInfo]
go Block
d
go Block
_ = [Tree SecInfo] -> [Tree SecInfo]
forall a. a -> a
id
fixTOCTreePaths :: [Chunk] -> Tree SecInfo -> Tree SecInfo
fixTOCTreePaths :: [Chunk] -> Tree SecInfo -> Tree SecInfo
fixTOCTreePaths [Chunk]
chunks = String -> Tree SecInfo -> Tree SecInfo
go String
""
where
idMap :: Map Text String
idMap = (Chunk -> Map Text String -> Map Text String)
-> Map Text String -> [Chunk] -> Map Text String
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Chunk
chunk Map Text String
m ->
let ids :: [Text]
ids = (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
T.null)
(Chunk -> Text
chunkId Chunk
chunk Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:
(Block -> [Text]) -> [Block] -> [Text]
forall c. Monoid c => (Block -> c) -> [Block] -> c
forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
query Block -> [Text]
getIds (Chunk -> [Block]
chunkContents Chunk
chunk))
in (Text -> Map Text String -> Map Text String)
-> Map Text String -> [Text] -> Map Text String
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Text
i -> Text -> String -> Map Text String -> Map Text String
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
i (Chunk -> String
chunkPath Chunk
chunk)) Map Text String
m [Text]
ids)
Map Text String
forall a. Monoid a => a
mempty [Chunk]
chunks
getIds :: Block -> [Text]
getIds :: Block -> [Text]
getIds (Div (Text
i,Text
"section":[Text]
_,[(Text, Text)]
_) [Block]
_) = [Text
i]
getIds Block
_ = []
go :: FilePath -> Tree SecInfo -> Tree SecInfo
go :: String -> Tree SecInfo -> Tree SecInfo
go String
fp (Node SecInfo
secinfo [Tree SecInfo]
subtrees) =
let newpath :: Maybe String
newpath = Text -> Map Text String -> Maybe String
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup (SecInfo -> Text
secId SecInfo
secinfo) Map Text String
idMap
fp' :: String
fp' = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
fp Maybe String
newpath
fragment :: Text
fragment = Text
"#" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SecInfo -> Text
secId SecInfo
secinfo
in SecInfo -> [Tree SecInfo] -> Tree SecInfo
forall a. a -> [Tree a] -> Tree a
Node SecInfo
secinfo{ secPath = T.pack fp' <> fragment }
((Tree SecInfo -> Tree SecInfo) -> [Tree SecInfo] -> [Tree SecInfo]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Tree SecInfo -> Tree SecInfo
go String
fp') [Tree SecInfo]
subtrees)
tocEntryToLink :: Bool -> SecInfo -> [Inline]
tocEntryToLink :: Bool -> SecInfo -> [Inline]
tocEntryToLink Bool
includeNumbers SecInfo
secinfo = [Inline]
headerLink
where
addNumber :: [Inline] -> [Inline]
addNumber = case SecInfo -> Maybe Text
secNumber SecInfo
secinfo of
Just Text
num | Bool
includeNumbers
-> ((Text, [Text], [(Text, Text)]) -> [Inline] -> Inline
Span (Text
"",[Text
"toc-section-number"],[])
[Text -> Inline
Str Text
num] Inline -> [Inline] -> [Inline]
forall a. a -> [a] -> [a]
:) ([Inline] -> [Inline])
-> ([Inline] -> [Inline]) -> [Inline] -> [Inline]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Inline
Space Inline -> [Inline] -> [Inline]
forall a. a -> [a] -> [a]
:)
Maybe Text
_ -> [Inline] -> [Inline]
forall a. a -> a
id
clean :: Inline -> [Inline]
clean (Link (Text, [Text], [(Text, Text)])
_ [Inline]
xs (Text, Text)
_) = [Inline]
xs
clean (Note [Block]
_) = []
clean Inline
x = [Inline
x]
anchor :: Text
anchor = if Text -> Bool
T.null (SecInfo -> Text
secPath SecInfo
secinfo)
then if Text -> Bool
T.null (SecInfo -> Text
secId SecInfo
secinfo)
then Text
""
else Text
"#" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SecInfo -> Text
secId SecInfo
secinfo
else SecInfo -> Text
secPath SecInfo
secinfo
headerText :: [Inline]
headerText = [Inline] -> [Inline]
addNumber ([Inline] -> [Inline]) -> [Inline] -> [Inline]
forall a b. (a -> b) -> a -> b
$ ([Inline] -> [Inline]) -> [Inline] -> [Inline]
forall a b. Walkable a b => (a -> a) -> b -> b
walk ((Inline -> [Inline]) -> [Inline] -> [Inline]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Inline -> [Inline]
clean) (SecInfo -> [Inline]
secTitle SecInfo
secinfo)
headerLink :: [Inline]
headerLink = if Text -> Bool
T.null Text
anchor
then [Inline]
headerText
else [(Text, [Text], [(Text, Text)])
-> [Inline] -> (Text, Text) -> Inline
Link ((if Text -> Bool
T.null (SecInfo -> Text
secId SecInfo
secinfo)
then Text
""
else Text
"toc-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SecInfo -> Text
secId SecInfo
secinfo), [], [])
[Inline]
headerText (Text
anchor, Text
"")]
tocToList :: Bool -> Int -> Tree SecInfo -> Block
tocToList :: Bool -> Int -> Tree SecInfo -> Block
tocToList Bool
includeNumbers Int
tocDepth (Node SecInfo
_ [Tree SecInfo]
subtrees) = [[Block]] -> Block
BulletList ([Tree SecInfo] -> [[Block]]
toItems [Tree SecInfo]
subtrees)
where
toItems :: [Tree SecInfo] -> [[Block]]
toItems = (Tree SecInfo -> [Block]) -> [Tree SecInfo] -> [[Block]]
forall a b. (a -> b) -> [a] -> [b]
map Tree SecInfo -> [Block]
go ([Tree SecInfo] -> [[Block]])
-> ([Tree SecInfo] -> [Tree SecInfo])
-> [Tree SecInfo]
-> [[Block]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tree SecInfo -> Bool) -> [Tree SecInfo] -> [Tree SecInfo]
forall a. (a -> Bool) -> [a] -> [a]
filter Tree SecInfo -> Bool
isBelowTocDepth
isBelowTocDepth :: Tree SecInfo -> Bool
isBelowTocDepth (Node SecInfo
sec [Tree SecInfo]
_) = SecInfo -> Int
secLevel SecInfo
sec Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
tocDepth
go :: Tree SecInfo -> [Block]
go (Node SecInfo
secinfo [Tree SecInfo]
xs) =
[Inline] -> Block
Plain (Bool -> SecInfo -> [Inline]
tocEntryToLink Bool
includeNumbers SecInfo
secinfo) Block -> [Block] -> [Block]
forall a. a -> [a] -> [a]
:
case [Tree SecInfo] -> [[Block]]
toItems [Tree SecInfo]
xs of
[] -> []
[[Block]]
ys -> [[[Block]] -> Block
BulletList [[Block]]
ys]