    {-# LANGUAGE TupleSections #-}
    {-# LANGUAGE OverloadedStrings #-}
    {- |
       Module      : Text.Pandoc.Readers.EndNote
       Copyright   : Copyright (C) 2022-2024 John MacFarlane
       License     : GNU GPL, version 2 or above

       Maintainer  : John MacFarlane <jgm@berkeley.edu>
       Stability   : alpha
       Portability : portable

    Parses EndNote XML bibliographies into a Pandoc document
    with empty body and `references` and `nocite` fields
    in the metadata.  A wildcard `nocite` is used so that
    if the document is rendered in another format, the
    entire bibliography will be printed.
    -}
    module Text.Pandoc.Readers.EndNote
      ( readEndNoteXML
      , readEndNoteXMLCitation
      )
    where

    import Text.Pandoc.Options
    import Text.Pandoc.Definition
    import Citeproc (Reference(..), ItemId(..), Val(..), Date(..), DateParts(..))
    import qualified Citeproc
    import Text.Pandoc.Builder as B
    import Text.Pandoc.Error (PandocError(..))
    import Text.Pandoc.Class (PandocMonad)
    import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue)
    import Text.Pandoc.Sources (Sources(..), ToSources(..), sourcesToText)
    import Text.Pandoc.Citeproc.Name (toName, NameOpts(..))
    import Control.Applicative ((<|>))
    import Control.Monad.Except (throwError)
    import Control.Monad (mzero, unless)
    import Text.Pandoc.XML.Light
        ( filterElementName,
          strContent,
          QName(qName),
          Element(..),
          Content(..),
          CData(..),
          filterElementsName,
          filterChildName,
          filterChildrenName,
          findAttrBy,
          parseXMLElement )
    import qualified Data.Text.Lazy as TL
    import qualified Data.Text as T
    import Data.Text (Text)
    import qualified Data.Map as M
    import Safe (readMay)

    -- | Read EndNote XML from an input string and return a Pandoc document.
    -- The document will have only metadata, with an empty body.
    -- The metadata will contain a `references` field with the
    -- bibliography entries, and a `nocite` field with the wildcard `[@*]`.
    readEndNoteXML :: (PandocMonad m, ToSources a)
                   => ReaderOptions -> a -> m Pandoc
    readEndNoteXML :: forall (m :: * -> *) a.
    (PandocMonad m, ToSources a) =>
    ReaderOptions -> a -> m Pandoc
    readEndNoteXML ReaderOptions
    _opts a
    inp = do
      let sources :: Sources
    sources = a -> Sources
    forall a. ToSources a => a -> Sources
    toSources a
    inp
      refs <- Sources -> m [Reference Text]
    forall (m :: * -> *).
    PandocMonad m =>
    Sources -> m [Reference Text]
    readEndNoteXMLReferences Sources
    sources m [Reference Text]
    -> ([Reference Text] -> m [Reference Inlines])
    -> m [Reference Inlines]
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (Reference Text -> m (Reference Inlines))
    -> [Reference Text] -> m [Reference Inlines]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM ((Text -> m Inlines) -> Reference Text -> m (Reference Inlines)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Reference a -> f (Reference b)
    traverse (Inlines -> m Inlines
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Inlines -> m Inlines) -> (Text -> Inlines) -> Text -> m Inlines
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Inlines
    text))
      return $
        setMeta "nocite" (cite [Citation {citationId = "*"
                                         , citationPrefix = []
                                         , citationSuffix = []
                                         , citationMode = NormalCitation
                                         , citationNoteNum = 0
                                         , citationHash = 0}] (str "[@*]")) $
        setMeta "references" (map referenceToMetaValue refs) $
        B.doc mempty

    readEndNoteXMLCitation :: PandocMonad m
                        => Text -> m (Citeproc.Citation Text)
    readEndNoteXMLCitation :: forall (m :: * -> *). PandocMonad m => Text -> m (Citation Text)
    readEndNoteXMLCitation Text
    xml = do
      tree <- (Text -> m Element)
    -> (Element -> m Element) -> Either Text Element -> m Element
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (PandocError -> m Element
    forall a. PandocError -> m a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> m Element)
    -> (Text -> PandocError) -> Text -> m Element
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text -> PandocError
    PandocXMLError Text
    "EndNote references") Element -> m Element
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either Text Element -> m Element)
    -> Either Text Element -> m Element
    forall a b. (a -> b) -> a -> b
    $
                  Text -> Either Text Element
    parseXMLElement (Text -> Text
    TL.fromStrict Text
    xml)
      unless (qName (elName tree) == "EndNote") $
        throwError $ PandocXMLError "EndNote references" "Expected EndNote element"
      let items = (Element -> CitationItem Text) -> [Element] -> [CitationItem Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Element -> CitationItem Text
    toCitationItem ([Element] -> [CitationItem Text])
    -> [Element] -> [CitationItem Text]
    forall a b. (a -> b) -> a -> b
    $ (QName -> Bool) -> Element -> [Element]
    filterElementsName (Text -> QName -> Bool
    name Text
    "Cite") Element
    tree
      return $ Citeproc.Citation{
                         Citeproc.citationId = Nothing
                       , Citeproc.citationNoteNumber = Nothing
                       , Citeproc.citationItems = items
                       }

    readEndNoteXMLReferences :: PandocMonad m
                             => Sources -> m [Reference Text]
    readEndNoteXMLReferences :: forall (m :: * -> *).
    PandocMonad m =>
    Sources -> m [Reference Text]
    readEndNoteXMLReferences Sources
    sources = do
      tree <- (Text -> m Element)
    -> (Element -> m Element) -> Either Text Element -> m Element
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (PandocError -> m Element
    forall a. PandocError -> m a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> m Element)
    -> (Text -> PandocError) -> Text -> m Element
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text -> PandocError
    PandocXMLError Text
    "EndNote references") Element -> m Element
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either Text Element -> m Element)
    -> Either Text Element -> m Element
    forall a b. (a -> b) -> a -> b
    $
                  Text -> Either Text Element
    parseXMLElement (Text -> Text
    TL.fromStrict (Text -> Text) -> (Sources -> Text) -> Sources -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Sources -> Text
    sourcesToText (Sources -> Text) -> Sources -> Text
    forall a b. (a -> b) -> a -> b
    $ Sources
    sources)
      let records = (QName -> Bool) -> Element -> [Element]
    filterElementsName (Text -> QName -> Bool
    name Text
    "record") Element
    tree
      return $ map recordToReference records

    toCitationItem :: Element -> Citeproc.CitationItem Text
    toCitationItem :: Element -> CitationItem Text
    toCitationItem Element
    el =
        Citeproc.CitationItem{ citationItemId :: ItemId
    Citeproc.citationItemId =
                                  ItemId
    -> (Reference Text -> ItemId) -> Maybe (Reference Text) -> ItemId
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe ItemId
    forall a. Monoid a => a
    mempty Reference Text -> ItemId
    forall a. Reference a -> ItemId
    referenceId Maybe (Reference Text)
    mbref
                             , citationItemLabel :: Maybe Text
    Citeproc.citationItemLabel = Maybe Text
    forall a. Maybe a
    Nothing
                             , citationItemLocator :: Maybe Text
    Citeproc.citationItemLocator = Maybe Text
    mbpages
                             , citationItemType :: CitationItemType
    Citeproc.citationItemType = CitationItemType
    Citeproc.NormalCite
                             , citationItemPrefix :: Maybe Text
    Citeproc.citationItemPrefix = Maybe Text
    mbprefix
                             , citationItemSuffix :: Maybe Text
    Citeproc.citationItemSuffix = Maybe Text
    mbsuffix
                             , citationItemData :: Maybe (Reference Text)
    Citeproc.citationItemData = Maybe (Reference Text)
    mbref
                             }
     where
      mbref :: Maybe (Reference Text)
    mbref = Element -> Reference Text
    recordToReference (Element -> Reference Text)
    -> Maybe Element -> Maybe (Reference Text)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (QName -> Bool) -> Element -> Maybe Element
    filterChildName (Text -> QName -> Bool
    name Text
    "record") Element
    el
      mbprefix :: Maybe Text
    mbprefix = Element -> Text
    getText (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (QName -> Bool) -> Element -> Maybe Element
    filterChildName (Text -> QName -> Bool
    name Text
    "Prefix") Element
    el
      mbsuffix :: Maybe Text
    mbsuffix = Element -> Text
    getText (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (QName -> Bool) -> Element -> Maybe Element
    filterChildName (Text -> QName -> Bool
    name Text
    "Suffix") Element
    el
      mbpages :: Maybe Text
    mbpages  = Element -> Text
    getText (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (QName -> Bool) -> Element -> Maybe Element
    filterChildName (Text -> QName -> Bool
    name Text
    "Pages") Element
    el

    name :: Text -> (QName -> Bool)
    name :: Text -> QName -> Bool
    name Text
    t = (Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    t) (Text -> Bool) -> (QName -> Text) -> QName -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . QName -> Text
    qName

    getText :: Element -> Text
    getText :: Element -> Text
    getText Element
    el = Content -> Text
    getText' (Element -> Content
    Elem Element
    el)
     where
      getText' :: Content -> Text
    getText' (Elem Element
    el') = [Text] -> Text
    forall a. Monoid a => [a] -> a
    mconcat ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ (Content -> Text) -> [Content] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Content -> Text
    getText' ([Content] -> [Text]) -> [Content] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Element -> [Content]
    elContent Element
    el'
      getText' (Text CData
    cd) = CData -> Text
    cdData CData
    cd
      getText' (CRef Text
    _) = Text
    forall a. Monoid a => a
    mempty

    recordToReference :: Element -> Reference Text
    recordToReference :: Element -> Reference Text
    recordToReference Element
    e =
      Reference{ referenceId :: ItemId
    referenceId = Text -> ItemId
    ItemId Text
    refid,
                 referenceType :: Text
    referenceType = Text
    reftype,
                 referenceDisambiguation :: Maybe DisambiguationData
    referenceDisambiguation = Maybe DisambiguationData
    forall a. Maybe a
    Nothing,
                 referenceVariables :: Map Variable (Val Text)
    referenceVariables = Map Variable (Val Text)
    refvars }

     where
       -- get strContent, recursing inside style elements:
       refid :: Text
    refid = Text -> (Element -> Text) -> Maybe Element -> Text
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Text
    forall a. Monoid a => a
    mempty (Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    strContent)
               ((QName -> Bool) -> Element -> Maybe Element
    filterElementName (Text -> QName -> Bool
    name Text
    "key") Element
    e
                Maybe Element -> Maybe Element -> Maybe Element
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> (QName -> Bool) -> Element -> Maybe Element
    filterElementName (Text -> QName -> Bool
    name Text
    "rec-number") Element
    e)
       reftype :: Text
    reftype = Text -> (Text -> Text) -> Maybe Text -> Text
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Text
    "document" Text -> Text
    toCslReferenceType
                  ((QName -> Bool) -> Element -> Maybe Element
    filterElementName (Text -> QName -> Bool
    name Text
    "ref-type") Element
    e Maybe Element -> (Element -> Maybe Text) -> Maybe Text
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
                    (QName -> Bool) -> Element -> Maybe Text
    findAttrBy (Text -> QName -> Bool
    name Text
    "name"))
       authors :: [Name]
    authors =
         (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "contributors") Element
    e [Element] -> (Element -> [Element]) -> [Element]
    forall a b. [a] -> (a -> [b]) -> [b]
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
         (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "authors") [Element] -> (Element -> [Element]) -> [Element]
    forall a b. [a] -> (a -> [b]) -> [b]
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
         (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "author") [Element] -> (Element -> [Name]) -> [Name]
    forall a b. [a] -> (a -> [b]) -> [b]
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
              NameOpts -> [Inline] -> [Name]
    forall (m :: * -> *). Monad m => NameOpts -> [Inline] -> m Name
    toName NameOpts{ nameOptsPrefixIsNonDroppingParticle :: Bool
    nameOptsPrefixIsNonDroppingParticle = Bool
    False
                             , nameOptsUseJuniorComma :: Bool
    nameOptsUseJuniorComma = Bool
    False }
                 ([Inline] -> [Name]) -> (Element -> [Inline]) -> Element -> [Name]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Inlines -> [Inline]
    forall a. Many a -> [a]
    B.toList (Inlines -> [Inline])
    -> (Element -> Inlines) -> Element -> [Inline]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .  Text -> Inlines
    B.text (Text -> Inlines) -> (Element -> Text) -> Element -> Inlines
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText
       titles :: [(Variable, Val Text)]
    titles = do
         x <- (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "titles") Element
    e
         (key, name') <- [("title", "title"),
                          ("container-title", "secondary-title")]
         (key,) . FancyVal . T.strip . getText <$>
                        filterChildrenName (name name') x
       pages :: [(Variable, Val Text)]
    pages = (Variable
    "pages",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "pages") Element
    e
       volume :: [(Variable, Val Text)]
    volume = (Variable
    "volume",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "volume") Element
    e
       number :: [(Variable, Val Text)]
    number = (Variable
    "number",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "number") Element
    e
       isbn :: [(Variable, Val Text)]
    isbn = (Variable
    "isbn",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "isbn") Element
    e
       publisher :: [(Variable, Val Text)]
    publisher = (Variable
    "publisher",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "publisher") Element
    e
       originalPublisher :: [(Variable, Val Text)]
    originalPublisher =
         (Variable
    "original-publisher",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "orig-pub") Element
    e
       publisherPlace :: [(Variable, Val Text)]
    publisherPlace =
         (Variable
    "publisher-place",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "pub-location") Element
    e
       abstract :: [(Variable, Val Text)]
    abstract = (Variable
    "abstract",) (Val Text -> (Variable, Val Text))
    -> (Element -> Val Text) -> Element -> (Variable, Val Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Val Text
    forall a. a -> Val a
    FancyVal (Text -> Val Text) -> (Element -> Text) -> Element -> Val Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.strip (Text -> Text) -> (Element -> Text) -> Element -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Text
    getText (Element -> (Variable, Val Text))
    -> [Element] -> [(Variable, Val Text)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                    (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "abstract") Element
    e
       dates :: [(Variable, Val a)]
    dates = (Variable
    "issued",) (Val a -> (Variable, Val a))
    -> (Element -> Val a) -> Element -> (Variable, Val a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Element -> Val a
    forall {a}. Element -> Val a
    toDate (Element -> (Variable, Val a)) -> [Element] -> [(Variable, Val a)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "dates") Element
    e
       toDate :: Element -> Val a
    toDate Element
    e' = Date -> Val a
    forall a. Date -> Val a
    DateVal (Date -> Val a) -> Date -> Val a
    forall a b. (a -> b) -> a -> b
    $
        Date { dateParts :: [DateParts]
    dateParts = Element -> [DateParts]
    toDateParts Element
    e'
             , dateCirca :: Bool
    dateCirca = Bool
    False
             , dateSeason :: Maybe Int
    dateSeason = Maybe Int
    forall a. Maybe a
    Nothing
             , dateLiteral :: Maybe Text
    dateLiteral = Maybe Text
    forall a. Maybe a
    Nothing }
       toDateParts :: Element -> [DateParts]
    toDateParts Element
    e' = do
        x <- (QName -> Bool) -> Element -> [Element]
    filterChildrenName (Text -> QName -> Bool
    name Text
    "year") Element
    e'
        case readMay . T.unpack . T.strip . getText $ x of
          Maybe Int
    Nothing -> [DateParts]
    forall a. [a]
    forall (m :: * -> *) a. MonadPlus m => m a
    mzero
          Just Int
    y  -> DateParts -> [DateParts]
    forall a. a -> [a]
    forall (m :: * -> *) a. Monad m => a -> m a
    return (DateParts -> [DateParts]) -> DateParts -> [DateParts]
    forall a b. (a -> b) -> a -> b
    $ [Int] -> DateParts
    DateParts [Int
    y]

       refvars :: Map Variable (Val Text)
    refvars = [(Variable, Val Text)] -> Map Variable (Val Text)
    forall k a. Ord k => [(k, a)] -> Map k a
    M.fromList ([(Variable, Val Text)] -> Map Variable (Val Text))
    -> [(Variable, Val Text)] -> Map Variable (Val Text)
    forall a b. (a -> b) -> a -> b
    $
         [ (Variable
    "author", [Name] -> Val Text
    forall a. [Name] -> Val a
    NamesVal [Name]
    authors) | Bool -> Bool
    not ([Name] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Name]
    authors) ] [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    titles [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    pages [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    volume [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    number [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    isbn [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    forall {a}. [(Variable, Val a)]
    dates [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    publisher [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    originalPublisher [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    publisherPlace [(Variable, Val Text)]
    -> [(Variable, Val Text)] -> [(Variable, Val Text)]
    forall a. [a] -> [a] -> [a]
    ++
         [(Variable, Val Text)]
    abstract

    toCslReferenceType :: Text -> Text
    toCslReferenceType :: Text -> Text
    toCslReferenceType Text
    t =
      case Text
    t of
        Text
    "Aggregated Database" -> Text
    "dataset"
        Text
    "Ancient Text" -> Text
    "classic"
        Text
    "Artwork" -> Text
    "graphic"
        Text
    "Audiovisual Material" -> Text
    "graphic"
        Text
    "Bill" -> Text
    "legislation"
        Text
    "Blog" -> Text
    "post-weblog"
        Text
    "Book" -> Text
    "book"
        Text
    "Book Section" -> Text
    "chapter"
        Text
    "Case" -> Text
    "legal_case"
        Text
    "Catalog" -> Text
    "document"
        Text
    "Chart or Table" -> Text
    "graphic"
        Text
    "Classical Work" -> Text
    "classic"
        Text
    "Computer program" -> Text
    "software"
        Text
    "Conference Paper" -> Text
    "article"
        Text
    "Conference Proceedings" -> Text
    "periodical"
        Text
    "Dataset" -> Text
    "dataset"
        Text
    "Dictionary" -> Text
    "book"
        Text
    "Edited Book" -> Text
    "book"
        Text
    "Electronic Article" -> Text
    "article"
        Text
    "Electronic Book" -> Text
    "book"
        Text
    "Electronic Book Section" -> Text
    "chapter"
        Text
    "Encyclopedia" -> Text
    "book"
        Text
    "Equation" -> Text
    "document"
        Text
    "Figure" -> Text
    "graphic"
        Text
    "Film or Broadcast" -> Text
    "motion_picture"
        Text
    "Government Document" -> Text
    "document"
        Text
    "Grant" -> Text
    "document"
        Text
    "Hearing" -> Text
    "hearing"
        Text
    "Interview" -> Text
    "interview"
        Text
    "Journal Article" -> Text
    "article-journal"
        Text
    "Legal Rule or Regulation" -> Text
    "regulation"
        Text
    "Magazine Article" -> Text
    "article-magazine"
        Text
    "Manuscript" -> Text
    "manuscript"
        Text
    "Map" -> Text
    "map"
        Text
    "Music" -> Text
    "musical_score"
        Text
    "Newspaper Article" -> Text
    "article-newspaper"
        Text
    "Online Database" -> Text
    "dataset"
        Text
    "Online Multimedia" -> Text
    "webpage"
        Text
    "Pamphlet" -> Text
    "pamphlet"
        Text
    "Patent" -> Text
    "patent"
        Text
    "Personal Communication" -> Text
    "personal_communication"
        Text
    "Podcast" -> Text
    "document"
        Text
    "Press Release" -> Text
    "report"
        Text
    "Report" -> Text
    "report"
        Text
    "Serial" -> Text
    "periodical"
        Text
    "Standard" -> Text
    "standard"
        Text
    "Statute" -> Text
    "legislation"
        Text
    "Thesis" -> Text
    "thesis"
        Text
    "Unpublished Work" -> Text
    "unpublished"
        Text
    "Web Page" -> Text
    "webpage"
        Text
    _ -> Text
    "document"