{-# language OverloadedStrings, ExtendedDefaultRules #-} module Lucid.VegaLite (vegaEmbedHead, vegaEmbedBodyScript, mkVegaHtml) where import Lucid import Lucid.PreEscaped (scriptSrc) import qualified Data.Aeson as A -- import qualified Data.Text as T import qualified Data.Text.Encoding as T (decodeUtf8) import qualified Data.ByteString.Lazy as LBS import Data.Monoid vegaCDN, vegaLiteCDN, vegaEmbedCDN :: Monad m => HtmlT m () vegaCDN = scriptSrc "https://cdn.jsdelivr.net/npm/vega@3" vegaLiteCDN = scriptSrc "https://cdn.jsdelivr.net/npm/vega-lite@2.5.0" vegaEmbedCDN = scriptSrc "https://cdn.jsdelivr.net/npm/vega-embed@3" -- | Construct a HTML page that can render a vega-lite plot. The plot will be rendered by the vega-embed library. -- -- NB: the 'A.Value' parameter must contain a vega-lite JSON payload mkVegaHtml :: A.Value -> Html () mkVegaHtml vl = doctypehtml_ $ html_ $ do meta_ [charset_ "UTF-8"] head_ vegaEmbedHead with div_ [id_ "vis"] "" body_ $ vegaEmbedBodyScript vl -- | The statements for downloading the vega javascript blobs from the CDN. Must be in the document \ vegaEmbedHead :: Html () vegaEmbedHead = do vegaCDN vegaLiteCDN vegaEmbedCDN -- | The statement for embedding the vega JSON payload and initializing vega-embed. Must be in the \ block and referenced by a \
\ vegaEmbedBodyScript :: A.Value -> Html () vegaEmbedBodyScript vl = script_ $ T.decodeUtf8 $ LBS.toStrict ("const spec =" <> A.encode vl <> "; vegaEmbed('#vis', spec).then(result => console.log(result)).catch(console.warn);" :: LBS.ByteString)