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
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.
The function getUrlRender is used for converting Route (HandlerSite m) to Text, through the use of Monads. For instance:
routeToText :: MonadHandler m => Route (HandlerSite m) -> m Text
routeToText url = do
r <- getUrlRender
return $ r url
getTestR :: Text -> Handler Text
getTestR something = routeToText (TestR something)
But what if I want to pass in a query parameter? Could I do it without dealing directly with Texts? Another question, could I simplify the type declaration of the function routeToText?
I will use these urls to accomplish with a JSON API specification regarding pagination, I've created all the abstraction to work with it but I don't know how to implement a way to put a link like http://example.com/articles?page=2 in a concise way. If there is a even better way to put the link with the query parameter integrating it beautifully with the Aeson library without converting it to Text first, please, let me know.
I would like to extract the text contents from the below Html page. All the paragraphs from the <div>.
I use the xml-conduit package for html parsing and came up with the following code:
getWebPageContents :: Url -> IO [T.Text]
getWebPageContents u = do
cursor <- cursorFor u
return $ cursor $// filter &/ content
filter = element "div" >=> attributeIs "id" "article-body-blocks" &// element "p"
This will return most of the text but not the ones from the links("front page of today's Daily Mirror")
Could anyone help?
You need to filter to all the descendants of the p tags, not just the children. You probably just need to replace &/ content with &// content.
I have been following the yesod tutorial and I am stuck on how to build a unit test involving parameters in a view that also hit a database. Backtracking a little, I followed the Echo.hs example:
getEchoR :: Text -> Handler Html
getEchoR theText = do
defaultLayout $ do
$(widgetFile "echo")
The corresponding test, note I have to cast the parameter into Text using Data.Text.pack
yit "Echo some text" $ do
get $ EchoR $ pack "Hello"
statusIs 200
Now I have the model defined like so:
Tag
name Text
type Text
With a handler that can render that that obviously take a TagId as the parameter
getTagR :: TagId -> Handler Html
getTagR tagId = do
tag <- runDB $ get404 tagId
defaultLayout $ do
setTitle $ toHtml $ tagName tag
$(widgetFile "tag")
This is where the test fails.
yit "Get a tag" $ do
-- tagId is undefined
get $ TagR tagId
statusIs 200
I am not sure how to define the tagId. It wouldn't work with a String or Text or Num, and I can't seem to figure out how to generate one as I can't find any example code in various Data.Persist tutorials. Or better yet, some other way to call the get method.
You want to use the Key data constructor to construct an ID value, which takes a PersistValue as a parameter. A simple example of creating one is:
Key $ PersistInt64 5
Another option is to call get with a textual URL, e.g. get ("/tag/5" :: Text).
Since times have changed, I'll leave this note here to say that these days one would use something like:
fromBackendKey 5
See the docs for fromBackendKey.
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