Search code examples
happstack

Directly outputting pre-generated HTML with Happstack


I'm playing around with Haskell and Happstack and I'm trying to output string-based HTML directly without using formal Happstack functions. Specifically I'm trying to output SVG directly into the page (with <svg> ... </svg>) which comes from another module already fully generated as a string.

It's just a little toy program so I'm trying to avoid having to refactor the SVG generator module.

So my question is, in the following:

(f "<b> test </b>")

what is f such that test will appear in bold in my browser?

If that's not reasonably possible, what would be a more structured approach?


Solution

  • The easy way is to use toResponseBS:

    import Data.ByteString.Char8 as C
    import Data.ByteString.Lazy.Char8 as L
    svgToResponse svg = toResponseBS (C.pack "image/svg+xml") (L.pack $ "<svg>" ++ svg ++ "</svg>")
    

    Another option is to make a ToMessage instance:

    newtype SVG = SVG String
    instance ToMessage SVG where
        toContentType _ = C.pack "image/svg+xml"
        toMessage (SVG svg) = L.pack $ "<svg>" ++ svg ++ "</svg>"
    

    Now you can do toResponse (SVG svg) or even ok $ SVG svg but the latter will not compose well with non-SVG handlers via msum ...


    edit: The above is relevant for serving an SVG file from a handler but you actually asked for embedding SVG in HTML which I first missed.

    The answer depends on how you're generating your HTML.

    If you're using blaze-html you want to use the preEscapedToHtml function:

    preEscapedToHtml $ "<svg>" ++ svg ++ "</svg>"
    

    If you're using HSP you want to use the cdata or pcdata function (I can never remember which, so try both):

    <svg><% cdata svg %></svg>
    

    Hope that helps!