{-
pandoc-crossref is a pandoc filter for numbering figures,
equations, tables and cross-references to them.
Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-}

{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
module Text.Pandoc.CrossRef.References.List (listOf) where

import Data.List
import qualified Data.Map as M
import qualified Data.Text as T
import Text.Pandoc.Definition
import Data.Maybe

import Lens.Micro.Mtl
import Text.Pandoc.CrossRef.References.Types
import Text.Pandoc.CrossRef.Util.Options
import Text.Pandoc.CrossRef.Util.Util
import Text.Pandoc.CrossRef.Util.Template

listOf :: Options -> [Block] -> WS [Block]
listOf :: Options -> [Block] -> WS [Block]
listOf Options{outFormat :: Options -> Maybe Format
outFormat=Maybe Format
f} [Block]
x | Maybe Format -> Bool
isLatexFormat Maybe Format
f = forall (m :: * -> *) a. Monad m => a -> m a
return [Block]
x
listOf Options
opts (RawBlock Format
fmt Text
"\\listoffigures":[Block]
xs)
  | Format -> Bool
isLaTeXRawBlockFmt Format
fmt
  = forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Lens' References RefMap
imgRefs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text
-> Options
-> (Options -> BlockTemplate)
-> (Options -> [Block])
-> [Block]
-> RefMap
-> WS [Block]
makeList Text
"fig" Options
opts Options -> BlockTemplate
lofItemTemplate Options -> [Block]
lofTitle [Block]
xs
listOf Options
opts (RawBlock Format
fmt Text
"\\listoftables":[Block]
xs)
  | Format -> Bool
isLaTeXRawBlockFmt Format
fmt
  = forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Lens' References RefMap
tblRefs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text
-> Options
-> (Options -> BlockTemplate)
-> (Options -> [Block])
-> [Block]
-> RefMap
-> WS [Block]
makeList Text
"tbl" Options
opts Options -> BlockTemplate
lotItemTemplate Options -> [Block]
lotTitle [Block]
xs
listOf Options
opts (RawBlock Format
fmt Text
"\\listoflistings":[Block]
xs)
  | Format -> Bool
isLaTeXRawBlockFmt Format
fmt
  = forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Lens' References RefMap
lstRefs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text
-> Options
-> (Options -> BlockTemplate)
-> (Options -> [Block])
-> [Block]
-> RefMap
-> WS [Block]
makeList Text
"lst" Options
opts Options -> BlockTemplate
lolItemTemplate Options -> [Block]
lolTitle [Block]
xs
listOf Options
_ [Block]
x = forall (m :: * -> *) a. Monad m => a -> m a
return [Block]
x

makeList
  :: T.Text
  -> Options
  -> (Options
  -> BlockTemplate)
  -> (Options
  -> [Block])
  -> [Block]
  -> M.Map T.Text RefRec
  -> WS [Block]
makeList :: Text
-> Options
-> (Options -> BlockTemplate)
-> (Options -> [Block])
-> [Block]
-> RefMap
-> WS [Block]
makeList Text
pfx Options
o Options -> BlockTemplate
tf Options -> [Block]
titlef [Block]
xs RefMap
refs =
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Options -> [Block]
titlef Options
o forall a. Semigroup a => a -> a -> a
<> (Attr -> [Block] -> Block
Div (Text
"", [Text
"list", Text
"list-of-" forall a. Semigroup a => a -> a -> a
<> Text
pfx], []) [Block]
items forall a. a -> [a] -> [a]
: [Block]
xs)
  where
    items :: [Block]
items = forall a. a -> Maybe a -> a
fromMaybe [Block]
items'forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ([[Block]] -> Block) -> [[Block]] -> [Block] -> Maybe Block
mergeList forall a. Maybe a
Nothing [] [Block]
items'
    items' :: [Block]
items' = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (RefRec -> [Block]
itemChap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) [(Text, RefRec)]
refsSorted
    mergeList :: Maybe ([[Block]] -> Block) -> [[Block]] -> [Block] -> Maybe Block
mergeList Maybe ([[Block]] -> Block)
Nothing [[Block]]
acc (OrderedList ListAttributes
style [[Block]]
item : [Block]
ys) =
      Maybe ([[Block]] -> Block) -> [[Block]] -> [Block] -> Maybe Block
mergeList (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ ListAttributes -> [[Block]] -> Block
OrderedList ListAttributes
style) ([[Block]]
item forall a. Semigroup a => a -> a -> a
<> [[Block]]
acc) [Block]
ys
    mergeList Maybe ([[Block]] -> Block)
Nothing [[Block]]
acc (BulletList [[Block]]
item : [Block]
ys) =
      Maybe ([[Block]] -> Block) -> [[Block]] -> [Block] -> Maybe Block
mergeList (forall a. a -> Maybe a
Just [[Block]] -> Block
BulletList) ([[Block]]
item forall a. Semigroup a => a -> a -> a
<> [[Block]]
acc) [Block]
ys
    mergeList (Just [[Block]] -> Block
cons) [[Block]]
acc (OrderedList ListAttributes
style [[Block]]
item : [Block]
ys)
      | [[Block]] -> Block
cons [] forall a. Eq a => a -> a -> Bool
== ListAttributes -> [[Block]] -> Block
OrderedList ListAttributes
style [] =
      Maybe ([[Block]] -> Block) -> [[Block]] -> [Block] -> Maybe Block
mergeList (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ ListAttributes -> [[Block]] -> Block
OrderedList ListAttributes
style) ([[Block]]
item forall a. Semigroup a => a -> a -> a
<> [[Block]]
acc) [Block]
ys
    mergeList (Just [[Block]] -> Block
cons) [[Block]]
acc (BulletList [[Block]]
item : [Block]
ys)
      | [[Block]] -> Block
cons [] forall a. Eq a => a -> a -> Bool
== [[Block]] -> Block
BulletList[] =
      Maybe ([[Block]] -> Block) -> [[Block]] -> [Block] -> Maybe Block
mergeList (forall a. a -> Maybe a
Just [[Block]] -> Block
BulletList) ([[Block]]
item forall a. Semigroup a => a -> a -> a
<> [[Block]]
acc) [Block]
ys
    mergeList (Just [[Block]] -> Block
cons) [[Block]]
acc [] = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ [[Block]] -> Block
cons forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [[Block]]
acc
    mergeList Maybe ([[Block]] -> Block)
_ [[Block]]
_ [Block]
_ = forall a. Maybe a
Nothing
    refsSorted :: [(Text, RefRec)]
refsSorted = forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy forall {a} {a}. (a, RefRec) -> (a, RefRec) -> Ordering
compare' forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [(k, a)]
M.toList RefMap
refs
    compare' :: (a, RefRec) -> (a, RefRec) -> Ordering
compare'
      (a
_,RefRec{refIndex :: RefRec -> Index
refIndex=Index
i, refSubfigure :: RefRec -> Maybe Index
refSubfigure=Maybe Index
si})
      (a
_,RefRec{refIndex :: RefRec -> Index
refIndex=Index
j, refSubfigure :: RefRec -> Maybe Index
refSubfigure=Maybe Index
sj})
      = forall a. Ord a => a -> a -> Ordering
compare (Index
i, Maybe Index
si) (Index
j, Maybe Index
sj)
    itemChap :: RefRec -> [Block]
    itemChap :: RefRec -> [Block]
itemChap ref :: RefRec
ref@RefRec{Index
[Inline]
Maybe Index
refTitle :: RefRec -> [Inline]
refSubfigure :: Maybe Index
refTitle :: [Inline]
refIndex :: Index
refSubfigure :: RefRec -> Maybe Index
refIndex :: RefRec -> Index
..} = forall a b. MkTemplate a b => [Inline] -> [Inline] -> b -> [a]
applyTemplate (RefRec -> [Inline]
numWithChap RefRec
ref) [Inline]
refTitle (Options -> BlockTemplate
tf Options
o)
    numWithChap :: RefRec -> [Inline]
    numWithChap :: RefRec -> [Inline]
numWithChap RefRec{Index
[Inline]
Maybe Index
refSubfigure :: Maybe Index
refTitle :: [Inline]
refIndex :: Index
refTitle :: RefRec -> [Inline]
refSubfigure :: RefRec -> Maybe Index
refIndex :: RefRec -> Index
..} = case Maybe Index
refSubfigure of
      Maybe Index
Nothing ->
        let vars :: Map Text [Inline]
vars = forall k a. [(k, a)] -> Map k a
M.fromDistinctAscList
              [ (Text
"i", [Inline] -> Index -> [Inline]
chapPrefix (Options -> [Inline]
chapDelim Options
o) Index
refIndex)
              , (Text
"suf", forall a. Monoid a => a
mempty)
              , (Text
"t", [Inline]
refTitle)
              ]
        in forall a b. MkTemplate a b => Map Text [Inline] -> b -> [a]
applyTemplate' Map Text [Inline]
vars forall a b. (a -> b) -> a -> b
$ Options -> Text -> Template
refIndexTemplate Options
o Text
pfx
      Just Index
s ->
        let vars :: Map Text [Inline]
vars = forall k a. [(k, a)] -> Map k a
M.fromDistinctAscList
              [ (Text
"i", [Inline] -> Index -> [Inline]
chapPrefix (Options -> [Inline]
chapDelim Options
o) Index
refIndex)
              , (Text
"s", [Inline] -> Index -> [Inline]
chapPrefix (Options -> [Inline]
chapDelim Options
o) Index
s)
              , (Text
"suf", forall a. Monoid a => a
mempty)
              , (Text
"t", [Inline]
refTitle)
              ]
        in forall a b. MkTemplate a b => Map Text [Inline] -> b -> [a]
applyTemplate' Map Text [Inline]
vars forall a b. (a -> b) -> a -> b
$ Options -> Template
subfigureRefIndexTemplate Options
o