How to render blaze-svg markup within blaze-html

764 Views Asked by At

I want to include a svg diagram generated with blaze-svg directly in html generated with blaze-html. Both are based on blaze-markup, so I expected it to be easy.

diagram1 :: Svg
diagram1 = ... 

try1 :: Html
try1 = html $
  body $ do
    h1 "My first diagram"
    toHtml diagram1

try2 :: Html
try2 :: html $
  body $ do
    h1 "My first diagram"
    toHtml $ renderSvg diagram1

Both try1 and try2 passes the compiler but neither shows the diagram. What is the right way? Is it a problem with including the svg tag directly?

2

There are 2 best solutions below

1
On BEST ANSWER

try2 first generates a string representation of the SVG with renderSvg, escapes it (toHtml) and includes the result into the HTML output. Using it, you should see the source of the SVG instead of the resulting image.

try1 should actually work. toHtml is defined as the identity on the Svg type, so you could also just use diagram1 directly.

Here is a complete example that generates a HTML document with embedded SVG:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Prelude hiding (head)
import Text.Blaze.Svg11 hiding (title)
import Text.Blaze.Svg11.Attributes hiding (title)
import Text.Blaze.Html5
import Text.Blaze.Html.Renderer.Pretty

diagram1 :: Svg
diagram1 = svg ! width "100" ! height "100" $
  circle ! cx "50" ! cy "50" ! r "40" ! stroke "green"
         ! strokeWidth "4" ! fill "yellow"

try2 :: Html
try2 = docTypeHtml $ do
  head $ title "Works"
  body $ do
    h1 "My first diagram"
    diagram1

main :: IO ()
main = putStr $ renderHtml try2
0
On

Here is the example from the blaze-svg package modified to be embedded in an HTML document:

{-# LANGUAGE OverloadedStrings #-}
import Text.Blaze.Svg11 ((!), mkPath, rotate, l, m)
import qualified Text.Blaze.Svg11 as S
import qualified Text.Blaze.Svg11.Attributes as A
import Text.Blaze.Svg.Renderer.String (renderSvg)
import qualified Text.Blaze.Html5 as H
import Text.Blaze.Html.Renderer.Text
import qualified Data.Text.Lazy.IO as TL

main :: IO ()
main = do
  let a = renderHtml try1 -- renderSvg svgDoc
  TL.putStrLn a

try1 :: H.Html
try1 = H.html $
  H.body $ do
    H.h1 "My first diagram"
    svgDoc

-- svgDoc :: S.Svg
svgDoc = S.svg ! A.version "1.1" ! A.width "150" ! A.height "100" ! A.viewbox "0 0 3 2" $ do
    S.g ! A.transform makeTransform $ do
      S.rect ! A.width "1" ! A.height "2" ! A.fill "#008d46"
      S.rect ! A.width "1" ! A.height "2" ! A.fill "#ffffff"
      S.rect ! A.width "1" ! A.height "2" ! A.fill "#d2232c"
      S.path ! A.d makePath

makePath :: S.AttributeValue
makePath = mkPath $ do
  l 2 3
  m 4 5

makeTransform :: S.AttributeValue
makeTransform = rotate 50