{-# LANGUAGE OverloadedStrings #-} module Hakyll.Web.Elm (elmStandaloneCompiler) where import Data.Monoid ((<>), mempty) import Data.String (fromString) import Data.Traversable (traverse) import Control.Applicative ((<$>)) import Control.Monad.Error (throwError) import Hakyll import Text.Blaze (preEscapedToMarkup) import Text.Blaze.Html5 ((!)) import Text.Blaze.Html.Renderer.String (renderHtml) import qualified Elm.Internal.Utils as Elm import qualified Text.Blaze.Html5 as H import qualified Text.Blaze.Html5.Attributes as Attr {-| Compiles an elm file to a div and inline Javascript. Expects elm-runtime.js to have already been loaded on the page. Works for files that only import from modules in the elm runtime. -} elmStandaloneCompiler :: Compiler (Item String) elmStandaloneCompiler = cached cacheName $ do it <- getResourceBody case traverse compileModule it of Left err -> throwError [err] Right out -> return out where cacheName = "Hakyll.Web.Elm.elmStandaloneCompiler" compileModule :: String -> Either String String compileModule bod = html modul <$> js where modul = maybe "Main" id . Elm.moduleName $ bod js = Elm.compile bod html :: String -- ^ Module Name -> String -- ^ Generated Javascript -> String -- ^ HTML & JS html modul genJS = renderHtml $ node <> instantiate where node = H.div ! Attr.id (fromString modul) $ mempty instantiate = (H.script ! Attr.type_ "text/javascript") . preEscapedToMarkup . unlines $ [ genJS , "var div = document.getElementById('" <> modul <> "', div);" , "Elm.embed(Elm." <> modul <> ", div);" ]