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

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

    Parses BibTeX or BibLaTeX 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.BibTeX
      ( readBibTeX
      , readBibLaTeX
      )
    where

    import Text.Pandoc.Options
    import Text.Pandoc.Definition
    import Text.Pandoc.Builder (setMeta, cite, str)
    import Text.Pandoc.Parsing (fromParsecError)
    import Citeproc (Lang(..), parseLang)
    import Citeproc.Locale (getLocale)
    import Text.Pandoc.Error (PandocError(..))
    import Text.Pandoc.Class (PandocMonad, lookupEnv)
    import Text.Pandoc.Citeproc.BibTeX as BibTeX
    import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue)
    import Text.Pandoc.Sources (ToSources(..))
    import Control.Monad.Except (throwError)

    -- | Read BibTeX 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 `[@*]`.
    readBibTeX :: (PandocMonad m, ToSources a)
               => ReaderOptions -> a -> m Pandoc
    readBibTeX :: forall (m :: * -> *) a.
    (PandocMonad m, ToSources a) =>
    ReaderOptions -> a -> m Pandoc
    readBibTeX = Variant -> ReaderOptions -> a -> m Pandoc
    forall (m :: * -> *) a.
    (PandocMonad m, ToSources a) =>
    Variant -> ReaderOptions -> a -> m Pandoc
    readBibTeX' Variant
    BibTeX.Bibtex

    -- | Read BibLaTeX 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 `[@*]`.
    readBibLaTeX :: (PandocMonad m, ToSources a)
                 => ReaderOptions -> a -> m Pandoc
    readBibLaTeX :: forall (m :: * -> *) a.
    (PandocMonad m, ToSources a) =>
    ReaderOptions -> a -> m Pandoc
    readBibLaTeX = Variant -> ReaderOptions -> a -> m Pandoc
    forall (m :: * -> *) a.
    (PandocMonad m, ToSources a) =>
    Variant -> ReaderOptions -> a -> m Pandoc
    readBibTeX' Variant
    BibTeX.Biblatex

    readBibTeX' :: (PandocMonad m, ToSources a)
                => Variant -> ReaderOptions -> a -> m Pandoc
    readBibTeX' :: forall (m :: * -> *) a.
    (PandocMonad m, ToSources a) =>
    Variant -> ReaderOptions -> a -> m Pandoc
    readBibTeX' Variant
    variant ReaderOptions
    _opts a
    t = do
      mblangEnv <- Text -> m (Maybe Text)
    forall (m :: * -> *). PandocMonad m => Text -> m (Maybe Text)
    lookupEnv Text
    "LANG"
      let defaultLang = Text
    -> Maybe Text
    -> Maybe Text
    -> [Text]
    -> [(Text, [(Text, Text)])]
    -> [Text]
    -> Lang
    Lang Text
    "en" Maybe Text
    forall a. Maybe a
    Nothing (Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    "US") [] [] []
      let lang = case Maybe Text
    mblangEnv of
                  Maybe Text
    Nothing  -> Lang
    defaultLang
                  Just Text
    l   -> (String -> Lang) -> (Lang -> Lang) -> Either String Lang -> Lang
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (Lang -> String -> Lang
    forall a b. a -> b -> a
    const Lang
    defaultLang) Lang -> Lang
    forall a. a -> a
    id (Either String Lang -> Lang) -> Either String Lang -> Lang
    forall a b. (a -> b) -> a -> b
    $ Text -> Either String Lang
    parseLang Text
    l
      locale <- case getLocale lang of
                   Left CiteprocError
    e  ->
                     case Lang -> Either CiteprocError Locale
    getLocale (Text
    -> Maybe Text
    -> Maybe Text
    -> [Text]
    -> [(Text, [(Text, Text)])]
    -> [Text]
    -> Lang
    Lang Text
    "en" Maybe Text
    forall a. Maybe a
    Nothing (Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    "US") [] [] []) of
                       Right Locale
    l -> Locale -> m Locale
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Locale
    l
                       Left CiteprocError
    _  -> PandocError -> m Locale
    forall a. PandocError -> m a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> m Locale) -> PandocError -> m Locale
    forall a b. (a -> b) -> a -> b
    $ CiteprocError -> PandocError
    PandocCiteprocError CiteprocError
    e
                   Right Locale
    l -> Locale -> m Locale
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Locale
    l
      case BibTeX.readBibtexString variant locale (const True) t of
        Left ParseError
    e -> PandocError -> m Pandoc
    forall a. PandocError -> m a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> m Pandoc) -> PandocError -> m Pandoc
    forall a b. (a -> b) -> a -> b
    $ Sources -> ParseError -> PandocError
    fromParsecError (a -> Sources
    forall a. ToSources a => a -> Sources
    toSources a
    t) ParseError
    e
        Right [Reference Inlines]
    refs -> Pandoc -> m Pandoc
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Pandoc -> m Pandoc) -> Pandoc -> m Pandoc
    forall a b. (a -> b) -> a -> b
    $ Text -> [MetaValue] -> Pandoc -> Pandoc
    forall a b. (HasMeta a, ToMetaValue b) => Text -> b -> a -> a
    forall b. ToMetaValue b => Text -> b -> Pandoc -> Pandoc
    setMeta Text
    "references"
                                  ((Reference Inlines -> MetaValue)
    -> [Reference Inlines] -> [MetaValue]
    forall a b. (a -> b) -> [a] -> [b]
    map Reference Inlines -> MetaValue
    referenceToMetaValue [Reference Inlines]
    refs)
                             (Pandoc -> Pandoc) -> (Pandoc -> Pandoc) -> Pandoc -> Pandoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Inlines -> Pandoc -> Pandoc
    forall a b. (HasMeta a, ToMetaValue b) => Text -> b -> a -> a
    forall b. ToMetaValue b => Text -> b -> Pandoc -> Pandoc
    setMeta Text
    "nocite"
                                ([Citation] -> Inlines -> Inlines
    cite [Citation {citationId :: Text
    citationId = Text
    "*"
                                                , citationPrefix :: [Inline]
    citationPrefix = []
                                                , citationSuffix :: [Inline]
    citationSuffix = []
                                                , citationMode :: CitationMode
    citationMode = CitationMode
    NormalCitation
                                                , citationNoteNum :: Int
    citationNoteNum = Int
    0
                                                , citationHash :: Int
    citationHash = Int
    0}]
                                                (Text -> Inlines
    str Text
    "[@*]"))
                            (Pandoc -> Pandoc) -> Pandoc -> Pandoc
    forall a b. (a -> b) -> a -> b
    $ Meta -> [Block] -> Pandoc
    Pandoc Meta
    nullMeta []