{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
module Commonmark.ReferenceMap
  ( ReferenceMap(..)
  , LinkInfo(..)
  , emptyReferenceMap
  , insertReference
  , lookupReference
  ) where
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Map.Strict as M
import Data.Dynamic
import Commonmark.Types
#if !MIN_VERSION_base(4,13,0)
import Data.Typeable (Typeable)
#endif

-- | Lookup table for link references.
newtype ReferenceMap = ReferenceMap { ReferenceMap -> Map Text [Dynamic]
unReferenceMap :: M.Map Text [Dynamic] }
  deriving (Int -> ReferenceMap -> ShowS
[ReferenceMap] -> ShowS
ReferenceMap -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReferenceMap] -> ShowS
$cshowList :: [ReferenceMap] -> ShowS
show :: ReferenceMap -> String
$cshow :: ReferenceMap -> String
showsPrec :: Int -> ReferenceMap -> ShowS
$cshowsPrec :: Int -> ReferenceMap -> ShowS
Show)

data LinkInfo = LinkInfo{ LinkInfo -> Text
linkDestination :: !Text
                        , LinkInfo -> Text
linkTitle       :: !Text
                        , LinkInfo -> Attributes
linkAttributes  :: !Attributes
                        , LinkInfo -> Maybe SourcePos
linkPos         :: !(Maybe SourcePos)
                            -- ^ Position of the reference link definition
                            -- for references links.
                        }
     deriving (Int -> LinkInfo -> ShowS
[LinkInfo] -> ShowS
LinkInfo -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LinkInfo] -> ShowS
$cshowList :: [LinkInfo] -> ShowS
show :: LinkInfo -> String
$cshow :: LinkInfo -> String
showsPrec :: Int -> LinkInfo -> ShowS
$cshowsPrec :: Int -> LinkInfo -> ShowS
Show, Typeable)

emptyReferenceMap :: ReferenceMap
emptyReferenceMap :: ReferenceMap
emptyReferenceMap = Map Text [Dynamic] -> ReferenceMap
ReferenceMap forall k a. Map k a
M.empty

-- | Insert a link reference into a reference map.
insertReference :: Typeable a
                => Text -- ^ Reference label
                -> a
                -> ReferenceMap
                -> ReferenceMap
insertReference :: forall a. Typeable a => Text -> a -> ReferenceMap -> ReferenceMap
insertReference Text
label a
x (ReferenceMap Map Text [Dynamic]
m) =
  Map Text [Dynamic] -> ReferenceMap
ReferenceMap (forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. [a] -> [a] -> [a]
(++))
    (Text -> Text
T.toCaseFold forall a b. (a -> b) -> a -> b
$! Text -> Text
normalizeSpaces Text
label) [forall a. Typeable a => a -> Dynamic
toDyn a
x] Map Text [Dynamic]
m)

-- | Lookup a reference in a reference map.  If there are several
-- values at this key, we return the first one in the list that
-- can be converted to an 'a'.
lookupReference :: Typeable a
                => Text -- ^ Reference label
                -> ReferenceMap
                -> Maybe a
lookupReference :: forall a. Typeable a => Text -> ReferenceMap -> Maybe a
lookupReference Text
label (ReferenceMap Map Text [Dynamic]
m) =
  forall {a}. Typeable a => Maybe [Dynamic] -> Maybe a
getFirst forall a b. (a -> b) -> a -> b
$! forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup (Text -> Text
T.toCaseFold forall a b. (a -> b) -> a -> b
$! Text -> Text
normalizeSpaces Text
label) Map Text [Dynamic]
m
  where getFirst :: Maybe [Dynamic] -> Maybe a
getFirst Maybe [Dynamic]
Nothing       = forall a. Maybe a
Nothing
        getFirst (Just [])     = forall a. Maybe a
Nothing
        getFirst (Just (Dynamic
x:[Dynamic]
xs)) = case forall a. Typeable a => Dynamic -> Maybe a
fromDynamic Dynamic
x of
                                      Just !a
v  -> forall a. a -> Maybe a
Just a
v
                                      Maybe a
Nothing  -> Maybe [Dynamic] -> Maybe a
getFirst (forall a. a -> Maybe a
Just [Dynamic]
xs)

normalizeSpaces :: Text -> Text
normalizeSpaces :: Text -> Text
normalizeSpaces = [Text] -> Text
T.unwords forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.words