@@ -0,0 +1,93 @@
1+{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}
2+{-# OPTIONS_GHC -fno-warn-missing-fields #-}
4+module Language.Elm.Quasi (elm, elmFile) where
6+import Language.Haskell.TH.Quote
7+import Language.Haskell.TH
8+import Language.Haskell.Meta (parseExp)
10+import Data.Attoparsec.Text
11+import Data.Text as T (Text, pack, unpack, strip)
13+{- | This QuasiQuoter allows for literal embedding of elm source code within
14+ Haskell files. It is not responsible for the actual compilation Process.
19+ main = image \"someImage.jpg\"
23+ It also allows for simple variable interpolation using the ^{...} syntax.
24+ This is intended for e.g. embedding pre-rendered type-safe URLs.
25+ All interpolated variables must be a member of the Show typeclass. This
26+ is not tested with more complicated expressions, so it is recommended to
27+ restrict usage of interpolation to pre-calculated variables.
31+ > let google = "http://google.com"
33+ > main = text $ link ^{google} (toText "Google")
37+ How the elm code is compiled depends on how you intend to use it.
38+ Example uses are the included 'generateHtml' function as well as the
39+ "Language.Elm.Yesod" module.
44+ let chunks = flip map (getQChunks s) $ \c ->
47+ E t -> let Right e = parseExp t in appE [| show |] (return e)
48+ in appE [| concat |] (listE chunks)
51+{- | elmFile is a quoteFile wrapper around the 'elm' QuasiQuoter and allows for
52+ external elm source files to be embedded.
56+ [elmFile|elm-source/page.elm|]
59+ Please note that no spaces should be added before and after the filename.
61+elmFile :: QuasiQuoter
62+elmFile = quoteFile elm
65+ S String -- ^ A literal string
66+ | E String -- ^ An expression (must be of the Show typeclass)
70+{- thanks to mikeplus64 for providing an example QuasiQuoter that I could look at while writing this :) -}
71+getQChunks :: String -> [QChunk]
72+getQChunks si = let i = T.pack si
73+ Right m = parseOnly parser (strip i) in m
78+ txt <- takeTill (== '^')
79+ evt <- choice [expression, fmap (S . T.unpack) takeText]
82+ then return $ filter (not . blank) $ reverse (evt:(S . T.unpack) txt:s)
83+ else go (evt:(S . T.unpack) txt:s)
91+ expr <- takeTill (== '}')
93+ return $ (E . T.unpack) expr