module Data.Text.Prettyprint.Doc.Render.GraphViz (
render,
render',
GraphVizRenderError(..),
) where
import qualified Data.Text.Lazy as TL
import qualified Data.Text as T
import Control.Exception (
Exception,
displayException,
throw,
)
import Data.GraphViz.Attributes.Complete (
Label (HtmlLabel),
)
import qualified Data.GraphViz.Attributes.HTML as H
import Data.Text.Prettyprint.Doc (
Doc,
SimpleDocStream (..),
defaultLayoutOptions,
layoutPretty,
)
render :: Doc H.Attribute -> Label
render = HtmlLabel . H.Text . render' . layoutPretty defaultLayoutOptions
render' :: SimpleDocStream H.Attribute -> H.Text
render' =
let go cs = \case
SFail -> throw GVDocStreamFail
SEmpty -> []
SChar c ds -> renderText cs (T.singleton c) : go cs ds
SText _ txt ds -> renderText cs txt : go cs ds
SLine n ds -> H.Newline [] : renderText cs (T.replicate n " ") : go cs ds
SAnnPush col ds -> go (col : cs) ds
SAnnPop ds -> go (tailDef (throw GVEmptyStack) cs) ds
in go []
data GraphVizRenderError
= GVDocStreamFail
| GVEmptyStack
deriving (Eq, Ord, Read, Show)
instance Exception GraphVizRenderError where
displayException = \case
GVDocStreamFail -> t ++ "encountered failure in document stream"
GVEmptyStack -> t ++ "attempted to pop empty attribute stack"
where t = "Failed to render HTML for GraphViz: "
tailDef :: [a] -> [a] -> [a]
tailDef e = \case
[] -> e
_ : xs -> xs
renderText :: H.Attributes -> T.Text -> H.TextItem
renderText cs = H.Font cs . pure . H.Str . TL.fromStrict