I can find plenty of documentation on using blitz and other compiletime templating libraries with happstack but I would like to know how to use html files as templates.
Though there are many options, my favourite would be Heist, which would allow you to define a splice:
> factSplice :: (Monad m) => TemplateMonad m Template
> factSplice = do
> input <- getParamNode
> let text = T.unpack $ X.nodeText input
> n = read text :: Int
> return [X.TextNode $ T.pack $ show $ product [1..n]]
>
which could be used in a dynamic (loaded at runtime) HTML template:
<html>
<head>
<title>Factorial Page</title>
</head>
<body>
<h1>Factorial Page</h1>
<p>The factorial of 6 is <fact>6</fact></p>
</body>
</html>
To use heist in happstack, you'll need the happstack-heist package. For more detail and other options, see Using Heist.
The HStringTemplate package provides a very general runtime templating system for not only HTML, but any sort of text output:
http://hackage.haskell.org/packages/archive/HStringTemplate/0.6.6/doc/html/Text-StringTemplate.html
The HStringTemplate package integrates with Happstack nicely through a few extra instances provided by an optional package: http://hackage.haskell.org/package/happstack-hstringtemplate
Related
I want to fetch a website looking like this¹: naked unicode between tags
<html>
한국어
</html>
I'm currently using
openURL :: String -> IO String
openURL x = getResponseBody =<< simpleHTTP (getRequest x)
But when inspecting the string 한국어 is displayed as \237\149\156\234\181\173\236\150\180, 9 characters.
And what I want would be 3 escaped characters like \u???\u???\u???
I tried Text.pack on page where page <- openURL "url" but it's already to late then.
¹ If I let firefox show me the source, and page info says UTF-8
You need to decode the text, for example with Data.Text.Encoding.decodeUtf8 from text or Codec.Binary.UTF8.String.decodeString from utf8-string.
In a yesod application, I want to create URL attributes for a graph that will be rendered by graphviz , and I want to use interpolation. Ideally,
graphToDot nonClusteredParams { fmtNode = \ (n,l) ->
[ URL [whamlet| #{MyRoute ...} |]
} g
Of course, the types don't match:
attribute of URL is pure Text, but whamlet is monadic (widget)
when I replace by shamlet, type is fine, but it cannot interpolate: URL interpolation used, but no URL renderer provided
Is there an easy way to solve this?
This works: get the render function (in the monad), and apply (in pure code)
render <- getUrlRender
let d = graphToDot ...
[ URL $ render $ MyRoute ... ]
I found this here, where a similar problem is solved: https://github.com/yesodweb/yesod/wiki/Using-type-safe-urls-from-inside-javascript
I'm reading an HTML web page that contains literal accented words (Spanish):
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Web page</title>
<body>
<p>Título</p>
<p>Año</p>
<p>Ángel</p>
<p>¿por qué nos vamos?</p>
</body>
I'm using HXT:
...
let doc = readDocument [ withValidate no
, withInputEncoding iso8859_1
, withParseHTML yes
, withWarnings no
, withEncodingErrors no
, withCurl []] url
...
Using the option
withInputEncoding utf8
discard those chars, getting as result the following words: Ttulo, Ao, ngel, por qu nos vamos?
Using the option
withInputEncoding iso8859_1
convert those chars to strings, getting as result words like: Rom\225ntica, Man\180s, H\233ctor. Where \225, \180 or \233 are strings, not chars.
What is the best method/way/approach to properly manage this situation in HXT and get all words without modifications?
Thanks.
I bet you already have everything you need
Prelude> putStrLn $ read "\"Rom\225ntica\""
Romántica
Looks like you are looking to result of show applied to the string, not the string itself? Note that print uses show:
Prelude> print (read "\"Rom\225ntica\"" :: String)
"Rom\225ntica"
I have a Happstack program that dynamically converts Markdown documents to HTML using Text.Pandoc:
import qualified Text.Pandoc as Pandoc
...
return $ toResponse $ Pandoc.writeHtml Pandoc.def contents
I.e. Pandoc is returning a Text.Blaze.Html.Html value. (This has a ToMessage instance which means it can be used as a response to a request.)
How do I insert a custom CSS stylesheet into Pandoc's output? What if I want to customise the HTML e.g. by wrapping the <body> contents with some other elements?
When Pandoc's "standalone mode" option is enabled, it uses a template to format the output.
The template and its substitions variables can be set in the writerTemplate and writerVariables members of WriterOptions.
The command line tool has a default set of template it uses. You can see the default template for a format using e.g. pandoc -D html.
When using the library, the default is to use an empty template. You can get the default template programmatically using getDefaultTemplate.
Here's some example code:
import Text.Blaze.Html.Renderer.String
import Text.Pandoc
getHtmlOpts = do
template <- either (error . show) id
`fmap` getDefaultTemplate Nothing "html"
return $ def
{ writerStandalone = True
, writerTemplate = template
, writerVariables = [
("css", "/path/to/style.css"),
("header-includes",
"<style>p { background-color: magenta; }</style>")]
}
main = do
opts <- getHtmlOpts
putStrLn $ renderHtml $ writeHtml opts $ readMarkdown def "..."
You can also write your own template, call it for instance template.html and use the --template template.html option when calling pandoc from the command-line.
The documentation is at https://pandoc.org/MANUAL.html#templates, and the default template (for inspiration) is at https://raw.githubusercontent.com/jgm/pandoc-templates/master/default.html5.
Pandoc, when run from the command line, takes some arguments that allow you to insert something into the <head> tag (-H), before content (-B) and after content (-A). I don't know about Happstack, but surely there must be a way to pass these parameters to Pandoc.writeHtml
I'm using HStringTemplate to render a very simple template using a data structure to fill in the "holes". The result of the template rendering is just a String I fed toResponse with.
Even though this rendered template is valid html happstack uses text/plain for Content-Type.
What is the reason for this? Shouldn't text/html be default since it is a webserver?
Do I really need to use toResponseBS and set text/html by myself?
Here is the code that creates the ServerPart Response
data Person = Person
{ name :: String
, age ::Int
} deriving (Data, Typeable)
buildTemplate :: Person -> String -> FilePath -> ServerPart Response
buildTemplate fields name template = do
unrendered <- liftIO $ readFile template
ok $ toResponse $ renderTemplate name fields unrendered
renderTemplate :: String -> Person -> String -> String
renderTemplate name fields unrendered = toString rendered
where rendered = setAttribute name fields $ newSTMP unrendered
And here is the output from the webserver:
Head
Connection:Keep-Alive
Content-Type:text/plain; charset=UTF-8
Date:Wed, 09 Jan 2013 14:51:27 GMT
Server:Happstack/7.1.1
Transfer-Encoding:chunked
Body
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Memlikweb</title>
</head>
<body>
<h1>Hello, Richard!<h1>
<p>Do you have 25 for me?</p>
</body>
</html>
If you pass Text.Html to toResponse the content type will be text/html. You are passing a string, which toResponse takes to mean that the content type is plain text.
The happstack-hstringtemplate package provides an instance for ToMessage StringTemplate which means if you import it and then use toResponse on the template without rendering it, it will do the right thing.