xml-html-qq-0.1.0.0: src/Text/HTML/QQ.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{- |
Module : Text.HTML.QQ
Copyright : Dennis Gosnell 2017
License : BSD3
Maintainer : Dennis Gosnell (cdep.illabout@gmail.com)
Stability : experimental
Portability : unknown
This module provides a quasi-quoter for HTML 'Document's. See the 'html'
function for some examples.
See "Text.XML.QQ" for an explanation of the difference between "Text.HTML.QQ"
and "Text.XML.QQ".
-}
module Text.HTML.QQ
( html
, htmlRaw
-- * Types
, Document
) where
import Data.Text.Lazy (pack)
import Language.Haskell.TH (appE)
import Language.Haskell.TH.Quote (QuasiQuoter(..))
import Language.Haskell.TH.Syntax (lift)
import Text.Blaze.Renderer.Text (renderMarkup)
import Text.Heterocephalus (compileFromString, textSetting)
import Text.HTML.DOM (parseLT)
import Text.XML (Document)
import Text.XMLHTML.Internal (createExpQuasiQuoter)
-- $setup
-- >>> :set -XQuasiQuotes
-- >>> :set -XTemplateHaskell
-- | This 'QuasiQuoter' produces HTML 'Document's.
--
-- This 'QuasiQuoter' produces expressions of type 'Document'.
--
-- Here's a simple example of using it:
--
-- >>> [html|<html></html>|]
-- Document {documentPrologue = Prologue {prologueBefore = [], prologueDoctype = Nothing, prologueAfter = []}, documentRoot = Element {elementName = Name {nameLocalName = "html", nameNamespace = Nothing, namePrefix = Nothing}, elementAttributes = fromList [], elementNodes = []}, documentEpilogue = []}
--
-- Internally, this function is using the
-- <https://hackage.haskell.org/package/heterocephalus heterocephalus> package.
-- This means you can use variable interpolation, as well as @forall@, @if@,
-- and @case@ control statements. Checkout the
-- <https://github.com/arowM/heterocephalus#syntax heterocephalus README> for
-- more info.
--
-- >>> let a = "hello world"
-- >>> [html|<html>#{a}</html>|]
-- Document ...
--
-- Even invalid HTML will still parse.
--
-- >>> [html|<html </html>|]
-- Document ...
--
-- Here's an example of a template that can be parsed as an HTML 'Document', but
-- not as an XML 'Document':
--
-- >>> [html|<html><br></html>|]
-- Document ...
html :: QuasiQuoter
html =
createExpQuasiQuoter $ \string ->
appE [|parseLT . renderMarkup|] $ compileFromString textSetting string
-- | This function is the same as 'html', but doesn't allow variable
-- interpolation or control statements. It also produces expressions of type
-- 'Document'.
htmlRaw :: QuasiQuoter
htmlRaw = createExpQuasiQuoter $ lift . parseLT . pack