    {-# LANGUAGE CPP #-}
    {-# LANGUAGE TemplateHaskell #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# OPTIONS_GHC -fno-warn-missing-fields #-}
    -- | A Shakespearean module for Javascript templates, introducing type-safe,
    -- compile-time variable and url interpolation.--
    --
    -- You might consider trying 'Text.Typescript' or 'Text.Coffee' which compile down to Javascript.
    --
    -- Further reading: <http://www.yesodweb.com/book/shakespearean-templates>
    module Text.Julius
        ( -- * Functions
          -- ** Template-Reading Functions
          -- | These QuasiQuoter and Template Haskell methods return values of
          -- type @'JavascriptUrl' url@. See the Yesod book for details.
          js
        , julius
        , juliusFile
        , jsFile
        , juliusFileDebug
        , jsFileDebug
        , juliusFileReload
        , jsFileReload

          -- * Datatypes
        , JavascriptUrl
        , Javascript (..)
        , RawJavascript (..)

          -- * Typeclass for interpolated variables
        , ToJavascript (..)
        , RawJS (..)

          -- ** Rendering Functions
        , renderJavascript
        , renderJavascriptUrl

          -- ** internal, used by 'Text.Coffee'
        , javascriptSettings
          -- ** internal
        , juliusUsedIdentifiers
        , asJavascriptUrl
        ) where

    import Language.Haskell.TH.Quote (QuasiQuoter (..))
    import Language.Haskell.TH.Syntax
    import Data.Text.Lazy.Builder (Builder, fromText, toLazyText, fromLazyText)
    import Data.Monoid (Monoid(..))
    import Data.Semigroup (Semigroup(..))
    import qualified Data.Text as TS
    import qualified Data.Text.Lazy as TL
    import Text.Shakespeare
    import Data.Aeson (Value, toJSON)
    #if MIN_VERSION_aeson(2,0,0)
    import qualified Data.Aeson.KeyMap as KeyMap
    #endif
    import Data.Aeson.Types (Value(..))
    import Numeric (showHex)
    import qualified Data.HashMap.Strict as H
    import qualified Data.Vector as V
    import Data.Text.Lazy.Builder (singleton, fromString)
    import qualified Data.Text as T
    import Data.Scientific (FPFormat(..), Scientific, base10Exponent)
    import Data.Text.Lazy.Builder.Scientific (formatScientificBuilder)

    renderJavascript :: Javascript -> TL.Text
    renderJavascript :: Javascript -> Text
    renderJavascript (Javascript Builder
    b) = Builder -> Text
    toLazyText Builder
    b

    -- | render with route interpolation. If using this module standalone, apart
    -- from type-safe routes, a dummy renderer can be used:
    --
    -- > renderJavascriptUrl (\_ _ -> undefined) javascriptUrl
    --
    -- When using Yesod, a renderer is generated for you, which can be accessed
    -- within the GHandler monad: 'Yesod.Core.Handler.getUrlRenderParams'.
    renderJavascriptUrl :: (url -> [(TS.Text, TS.Text)] -> TS.Text) -> JavascriptUrl url -> TL.Text
    renderJavascriptUrl :: forall url.
    (url -> [(Text, Text)] -> Text) -> JavascriptUrl url -> Text
    renderJavascriptUrl url -> [(Text, Text)] -> Text
    r JavascriptUrl url
    s = Javascript -> Text
    renderJavascript (Javascript -> Text) -> Javascript -> Text
    forall a b. (a -> b) -> a -> b
    $ JavascriptUrl url
    s url -> [(Text, Text)] -> Text
    r

    -- | Newtype wrapper of 'Builder'.
    newtype Javascript = Javascript { Javascript -> Builder
    unJavascript :: Builder }
        deriving (NonEmpty Javascript -> Javascript
    Javascript -> Javascript -> Javascript
    (Javascript -> Javascript -> Javascript)
    -> (NonEmpty Javascript -> Javascript)
    -> (forall b. Integral b => b -> Javascript -> Javascript)
    -> Semigroup Javascript
    forall b. Integral b => b -> Javascript -> Javascript
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    $c<> :: Javascript -> Javascript -> Javascript
    <> :: Javascript -> Javascript -> Javascript
    $csconcat :: NonEmpty Javascript -> Javascript
    sconcat :: NonEmpty Javascript -> Javascript
    $cstimes :: forall b. Integral b => b -> Javascript -> Javascript
    stimes :: forall b. Integral b => b -> Javascript -> Javascript
    Semigroup, Semigroup Javascript
    Javascript
    Semigroup Javascript
    -> Javascript
    -> (Javascript -> Javascript -> Javascript)
    -> ([Javascript] -> Javascript)
    -> Monoid Javascript
    [Javascript] -> Javascript
    Javascript -> Javascript -> Javascript
    forall a.
    Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    $cmempty :: Javascript
    mempty :: Javascript
    $cmappend :: Javascript -> Javascript -> Javascript
    mappend :: Javascript -> Javascript -> Javascript
    $cmconcat :: [Javascript] -> Javascript
    mconcat :: [Javascript] -> Javascript
    Monoid)

    -- | Return type of template-reading functions.
    type JavascriptUrl url = (url -> [(TS.Text, TS.Text)] -> TS.Text) -> Javascript

    asJavascriptUrl :: JavascriptUrl url -> JavascriptUrl url
    asJavascriptUrl :: forall url. JavascriptUrl url -> JavascriptUrl url
    asJavascriptUrl = JavascriptUrl url -> JavascriptUrl url
    forall a. a -> a
    id

    -- | A typeclass for types that can be interpolated in CoffeeScript templates.
    class ToJavascript a where
        toJavascript :: a -> Javascript

    instance ToJavascript Bool where toJavascript :: Bool -> Javascript
    toJavascript = Builder -> Javascript
    Javascript (Builder -> Javascript) -> (Bool -> Builder) -> Bool -> Javascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Builder
    fromText (Text -> Builder) -> (Bool -> Text) -> Bool -> Builder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    TS.toLower (Text -> Text) -> (Bool -> Text) -> Bool -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Text
    TS.pack (String -> Text) -> (Bool -> String) -> Bool -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> String
    forall a. Show a => a -> String
    show
    instance ToJavascript Value where toJavascript :: Value -> Javascript
    toJavascript = Builder -> Javascript
    Javascript (Builder -> Javascript)
    -> (Value -> Builder) -> Value -> Javascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> Builder
    encodeToTextBuilder
    instance ToJavascript String where toJavascript :: String -> Javascript
    toJavascript = Value -> Javascript
    forall a. ToJavascript a => a -> Javascript
    toJavascript (Value -> Javascript) -> (String -> Value) -> String -> Javascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Value
    forall a. ToJSON a => a -> Value
    toJSON
    instance ToJavascript TS.Text where toJavascript :: Text -> Javascript
    toJavascript = Value -> Javascript
    forall a. ToJavascript a => a -> Javascript
    toJavascript (Value -> Javascript) -> (Text -> Value) -> Text -> Javascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Value
    forall a. ToJSON a => a -> Value
    toJSON
    instance ToJavascript TL.Text where toJavascript :: Text -> Javascript
    toJavascript = Value -> Javascript
    forall a. ToJavascript a => a -> Javascript
    toJavascript (Value -> Javascript) -> (Text -> Value) -> Text -> Javascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Value
    forall a. ToJSON a => a -> Value
    toJSON

    -- | Encode a JSON 'Value' to a "Data.Text" 'Builder', which can be
    -- embedded efficiently in a text-based protocol.
    --
    -- If you are going to immediately encode straight to a
    -- 'L.ByteString', it is more efficient to use 'encodeToBuilder'
    -- instead.
    encodeToTextBuilder :: Value -> Builder
    encodeToTextBuilder :: Value -> Builder
    encodeToTextBuilder =
        Value -> Builder
    go
      where
        go :: Value -> Builder
    go Value
    Null       = {-# SCC "go/Null" #-} Builder
    "null"
        go (Bool Bool
    b)   = {-# SCC "go/Bool" #-} if Bool
    b then Builder
    "true" else Builder
    "false"
        go (Number Scientific
    s) = {-# SCC "go/Number" #-} Scientific -> Builder
    fromScientific Scientific
    s
        go (String Text
    s) = {-# SCC "go/String" #-} Text -> Builder
    string Text
    s
        go (Array Array
    v)
            | Array -> Bool
    forall a. Vector a -> Bool
    V.null Array
    v = {-# SCC "go/Array" #-} Builder
    "[]"
            | Bool
    otherwise = {-# SCC "go/Array" #-}
                          Char -> Builder
    singleton Char
    '[' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <>
                          Value -> Builder
    go (Array -> Value
    forall a. Vector a -> a
    V.unsafeHead Array
    v) Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <>
                          (Value -> Builder -> Builder) -> Builder -> Array -> Builder
    forall a b. (a -> b -> b) -> b -> Vector a -> b
    V.foldr Value -> Builder -> Builder
    f (Char -> Builder
    singleton Char
    ']') (Array -> Array
    forall a. Vector a -> Vector a
    V.unsafeTail Array
    v)
          where f :: Value -> Builder -> Builder
    f Value
    a Builder
    z = Char -> Builder
    singleton Char
    ',' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Value -> Builder
    go Value
    a Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Builder
    z
        go (Object Object
    m) = {-# SCC "go/Object" #-}
            case Object -> [(Text, Value)]
    forall {v}. KeyMap v -> [(Text, v)]
    fromObject Object
    m of
              ((Text, Value)
    x:[(Text, Value)]
    xs) -> Char -> Builder
    singleton Char
    '{' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> (Text, Value) -> Builder
    one (Text, Value)
    x Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> ((Text, Value) -> Builder -> Builder)
    -> Builder -> [(Text, Value)] -> Builder
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (Text, Value) -> Builder -> Builder
    f (Char -> Builder
    singleton Char
    '}') [(Text, Value)]
    xs
              [(Text, Value)]
    _      -> Builder
    "{}"
          where f :: (Text, Value) -> Builder -> Builder
    f (Text, Value)
    a Builder
    z     = Char -> Builder
    singleton Char
    ',' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> (Text, Value) -> Builder
    one (Text, Value)
    a Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Builder
    z
                one :: (Text, Value) -> Builder
    one (Text
    k,Value
    v) = Text -> Builder
    string Text
    k Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Char -> Builder
    singleton Char
    ':' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Value -> Builder
    go Value
    v

    #if MIN_VERSION_aeson(2,0,0)
        fromObject :: KeyMap v -> [(Text, v)]
    fromObject = HashMap Text v -> [(Text, v)]
    forall k v. HashMap k v -> [(k, v)]
    H.toList (HashMap Text v -> [(Text, v)])
    -> (KeyMap v -> HashMap Text v) -> KeyMap v -> [(Text, v)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . KeyMap v -> HashMap Text v
    forall v. KeyMap v -> HashMap Text v
    KeyMap.toHashMapText
    #else
        fromObject = H.toList
    #endif

    string :: T.Text -> Builder
    string :: Text -> Builder
    string Text
    s = {-# SCC "string" #-} Char -> Builder
    singleton Char
    '"' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Text -> Builder
    quote Text
    s Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Char -> Builder
    singleton Char
    '"'
      where
        quote :: Text -> Builder
    quote Text
    q = case Text -> Maybe (Char, Text)
    T.uncons Text
    t of
                    Maybe (Char, Text)
    Nothing      -> Text -> Builder
    fromText Text
    h
                    Just (!Char
    c,Text
    t') -> Text -> Builder
    fromText Text
    h Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Char -> Builder
    escape Char
    c Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Text -> Builder
    quote Text
    t'
            where (Text
    h,Text
    t) = {-# SCC "break" #-} (Char -> Bool) -> Text -> (Text, Text)
    T.break Char -> Bool
    isEscape Text
    q
        isEscape :: Char -> Bool
    isEscape 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
    '\'' Bool -> Bool -> Bool
    ||
                     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
    '<'  Bool -> Bool -> Bool
    ||
                     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
    '&'  Bool -> Bool -> Bool
    ||
                     Char
    c Char -> Char -> Bool
    forall a. Ord a => a -> a -> Bool
    < Char
    '\x20'
        escape :: Char -> Builder
    escape Char
    '\"' = Builder
    "\\\""
        escape Char
    '\'' = Builder
    "\\\'"
        escape Char
    '\\' = Builder
    "\\\\"
        escape Char
    '\n' = Builder
    "\\n"
        escape Char
    '\r' = Builder
    "\\r"
        escape Char
    '\t' = Builder
    "\\t"
        escape Char
    '<' = Builder
    "\\u003c"
        escape Char
    '>' = Builder
    "\\u003e"
        escape Char
    '&' = Builder
    "\\u0026"

        escape Char
    c
            | Char
    c Char -> Char -> Bool
    forall a. Ord a => a -> a -> Bool
    < Char
    '\x20' = String -> Builder
    fromString (String -> Builder) -> String -> Builder
    forall a b. (a -> b) -> a -> b
    $ String
    "\\u" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> Char -> String
    forall a. Int -> a -> [a]
    replicate (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - String -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    h) Char
    '0' String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    h
            | Bool
    otherwise  = Char -> Builder
    singleton Char
    c
            where h :: String
    h = Int -> String -> String
    forall a. Integral a => a -> String -> String
    showHex (Char -> Int
    forall a. Enum a => a -> Int
    fromEnum Char
    c) String
    ""

    fromScientific :: Scientific -> Builder
    fromScientific :: Scientific -> Builder
    fromScientific Scientific
    s = FPFormat -> Maybe Int -> Scientific -> Builder
    formatScientificBuilder FPFormat
    format Maybe Int
    prec Scientific
    s
      where
        (FPFormat
    format, Maybe Int
    prec)
          | Scientific -> Int
    base10Exponent Scientific
    s Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0 = (FPFormat
    Generic, Maybe Int
    forall a. Maybe a
    Nothing)
          | Bool
    otherwise            = (FPFormat
    Fixed,   Int -> Maybe Int
    forall a. a -> Maybe a
    Just Int
    0)

    newtype RawJavascript = RawJavascript Builder
    instance ToJavascript RawJavascript where
        toJavascript :: RawJavascript -> Javascript
    toJavascript (RawJavascript Builder
    a) = Builder -> Javascript
    Javascript Builder
    a

    class RawJS a where
        rawJS :: a -> RawJavascript

    instance RawJS [Char] where rawJS :: String -> RawJavascript
    rawJS = Builder -> RawJavascript
    RawJavascript (Builder -> RawJavascript)
    -> (String -> Builder) -> String -> RawJavascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Builder
    fromLazyText (Text -> Builder) -> (String -> Text) -> String -> Builder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Text
    TL.pack
    instance RawJS TS.Text where rawJS :: Text -> RawJavascript
    rawJS = Builder -> RawJavascript
    RawJavascript (Builder -> RawJavascript)
    -> (Text -> Builder) -> Text -> RawJavascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Builder
    fromText
    instance RawJS TL.Text where rawJS :: Text -> RawJavascript
    rawJS = Builder -> RawJavascript
    RawJavascript (Builder -> RawJavascript)
    -> (Text -> Builder) -> Text -> RawJavascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Builder
    fromLazyText
    instance RawJS Builder where rawJS :: Builder -> RawJavascript
    rawJS = Builder -> RawJavascript
    RawJavascript
    instance RawJS Bool where rawJS :: Bool -> RawJavascript
    rawJS = Builder -> RawJavascript
    RawJavascript (Builder -> RawJavascript)
    -> (Bool -> Builder) -> Bool -> RawJavascript
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Javascript -> Builder
    unJavascript (Javascript -> Builder) -> (Bool -> Javascript) -> Bool -> Builder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> Javascript
    forall a. ToJavascript a => a -> Javascript
    toJavascript

    javascriptSettings :: Q ShakespeareSettings
    javascriptSettings :: Q ShakespeareSettings
    javascriptSettings = do
      Exp
    toJExp <- [|toJavascript|]
      Exp
    wrapExp <- [|Javascript|]
      Exp
    unWrapExp <- [|unJavascript|]
      Exp
    asJavascriptUrl' <- [|asJavascriptUrl|]
      ShakespeareSettings -> Q ShakespeareSettings
    forall a. a -> Q a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ShakespeareSettings -> Q ShakespeareSettings)
    -> ShakespeareSettings -> Q ShakespeareSettings
    forall a b. (a -> b) -> a -> b
    $ ShakespeareSettings
    defaultShakespeareSettings { toBuilder :: Exp
    toBuilder = Exp
    toJExp
      , wrap :: Exp
    wrap = Exp
    wrapExp
      , unwrap :: Exp
    unwrap = Exp
    unWrapExp
      , modifyFinalValue :: Maybe Exp
    modifyFinalValue = Exp -> Maybe Exp
    forall a. a -> Maybe a
    Just Exp
    asJavascriptUrl'
      }

    js, julius :: QuasiQuoter
    js :: QuasiQuoter
    js = QuasiQuoter { quoteExp :: String -> Q Exp
    quoteExp = \String
    s -> do
        ShakespeareSettings
    rs <- Q ShakespeareSettings
    javascriptSettings
        QuasiQuoter -> String -> Q Exp
    quoteExp (ShakespeareSettings -> QuasiQuoter
    shakespeare ShakespeareSettings
    rs) String
    s
        }

    julius :: QuasiQuoter
    julius = QuasiQuoter
    js

    jsFile, juliusFile :: FilePath -> Q Exp
    jsFile :: String -> Q Exp
    jsFile String
    fp = do
        ShakespeareSettings
    rs <- Q ShakespeareSettings
    javascriptSettings
        ShakespeareSettings -> String -> Q Exp
    shakespeareFile ShakespeareSettings
    rs String
    fp

    juliusFile :: String -> Q Exp
    juliusFile = String -> Q Exp
    jsFile

    jsFileReload, juliusFileReload :: FilePath -> Q Exp
    jsFileReload :: String -> Q Exp
    jsFileReload String
    fp = do
        ShakespeareSettings
    rs <- Q ShakespeareSettings
    javascriptSettings
        ShakespeareSettings -> String -> Q Exp
    shakespeareFileReload ShakespeareSettings
    rs String
    fp

    juliusFileReload :: String -> Q Exp
    juliusFileReload = String -> Q Exp
    jsFileReload

    jsFileDebug, juliusFileDebug :: FilePath -> Q Exp
    juliusFileDebug :: String -> Q Exp
    juliusFileDebug = String -> Q Exp
    jsFileReload
    {-# DEPRECATED juliusFileDebug "Please use juliusFileReload instead." #-}
    jsFileDebug :: String -> Q Exp
    jsFileDebug = String -> Q Exp
    jsFileReload
    {-# DEPRECATED jsFileDebug "Please use jsFileReload instead." #-}

    -- | Determine which identifiers are used by the given template, useful for
    -- creating systems like yesod devel.
    juliusUsedIdentifiers :: String -> [(Deref, VarType)]
    juliusUsedIdentifiers :: String -> [(Deref, VarType)]
    juliusUsedIdentifiers = ShakespeareSettings -> String -> [(Deref, VarType)]
    shakespeareUsedIdentifiers ShakespeareSettings
    defaultShakespeareSettings