-
Notifications
You must be signed in to change notification settings - Fork 76
/
Julius.hs
128 lines (107 loc) · 4.08 KB
/
Julius.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fno-warn-missing-fields #-}
-- | A Shakespearean module for Javascript templates, introducing type-safe,
-- compile-time variable and url interpolation.--
-- To use this module, @coffee@ must be installed on your system.
--
-- You might consider trying 'Text.Coffee', which compiles down to Javascript.
--
-- Further reading: <http://www.yesodweb.com/book/templates>
--
-- This module is currently in an identity crisis. Originally called Julius, now being changed to just Javascript (shakespeare-javascript)
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 (..)
-- * Typeclass for interpolated variables
, ToJavascript (..)
-- ** Rendering Functions
, renderJavascript
, renderJavascriptUrl
-- ** internal, used by 'Text.Coffee'
, javascriptSettings
-- ** internal
, juliusUsedIdentifiers
) where
import Language.Haskell.TH.Quote (QuasiQuoter (..))
import Language.Haskell.TH.Syntax
import Data.Text.Lazy.Builder (Builder, fromText, toLazyText, fromLazyText)
import Data.Monoid
import qualified Data.Text as TS
import qualified Data.Text.Lazy as TL
import Text.Shakespeare
renderJavascript :: Javascript -> TL.Text
renderJavascript (Javascript b) = toLazyText 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.Handler.getUrlRenderParams'.
renderJavascriptUrl :: (url -> [(TS.Text, TS.Text)] -> TS.Text) -> JavascriptUrl url -> TL.Text
renderJavascriptUrl r s = renderJavascript $ s r
-- | Newtype wrapper of 'Builder'.
newtype Javascript = Javascript { unJavascript :: Builder }
deriving Monoid
-- | Return type of template-reading functions.
type JavascriptUrl url = (url -> [(TS.Text, TS.Text)] -> TS.Text) -> Javascript
asJavascriptUrl :: JavascriptUrl url -> JavascriptUrl url
asJavascriptUrl = id
-- | A typeclass for types that can be interpolated in CoffeeScript templates.
class ToJavascript a where
toJavascript :: a -> Builder
instance ToJavascript [Char] where toJavascript = fromLazyText . TL.pack
instance ToJavascript TS.Text where toJavascript = fromText
instance ToJavascript TL.Text where toJavascript = fromLazyText
javascriptSettings :: Q ShakespeareSettings
javascriptSettings = do
toJExp <- [|toJavascript|]
wrapExp <- [|Javascript|]
unWrapExp <- [|unJavascript|]
asJavascriptUrl' <- [|asJavascriptUrl|]
return $ defaultShakespeareSettings { toBuilder = toJExp
, wrap = wrapExp
, unwrap = unWrapExp
, modifyFinalValue = Just asJavascriptUrl'
}
js, julius :: QuasiQuoter
js = QuasiQuoter { quoteExp = \s -> do
rs <- javascriptSettings
quoteExp (shakespeare rs) s
}
julius = js
jsFile, juliusFile :: FilePath -> Q Exp
jsFile fp = do
rs <- javascriptSettings
shakespeareFile rs fp
juliusFile = jsFile
jsFileReload, juliusFileReload :: FilePath -> Q Exp
jsFileReload fp = do
rs <- javascriptSettings
shakespeareFileReload rs fp
juliusFileReload = jsFileReload
jsFileDebug, juliusFileDebug :: FilePath -> Q Exp
juliusFileDebug = jsFileReload
{-# DEPRECATED juliusFileDebug "Please use juliusFileReload instead." #-}
jsFileDebug = 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 = shakespeareUsedIdentifiers defaultShakespeareSettings