0 | module Text.SVG.Node
  1 |
  2 | import Data.String
  3 | import Text.SVG.Attribute as A
  4 | import Text.SVG.Tag
  5 | import Text.SVG.Types
  6 |
  7 | %default total
  8 |
  9 | public export
 10 | data SVGNode : Type where
 11 |   El    :
 12 |        (tag : String)
 13 |     -> List (SVGAttribute tag)
 14 |     -> List SVGNode
 15 |     -> SVGNode
 16 |   Txt   : String -> SVGNode
 17 |   Raw   : String -> SVGNode
 18 |   Empty : SVGNode
 19 |
 20 | export %inline
 21 | el : (s : String) -> List (SVGAttribute s) -> SVGNode
 22 | el t as = El t as []
 23 |
 24 | export %inline
 25 | circle : List (SVGAttribute "circle") -> SVGNode
 26 | circle = el _
 27 |
 28 | export %inline
 29 | ellipse : List (SVGAttribute "ellipse") -> SVGNode
 30 | ellipse = el _
 31 |
 32 | export %inline
 33 | g : List (SVGAttribute "g") -> List SVGNode -> SVGNode
 34 | g = El _
 35 |
 36 | export %inline
 37 | image : List (SVGAttribute "image") -> SVGNode
 38 | image = el _
 39 |
 40 | export %inline
 41 | line : List (SVGAttribute "line") -> SVGNode
 42 | line = el _
 43 |
 44 | export %inline
 45 | mask : List (SVGAttribute "mask") -> List SVGNode -> SVGNode
 46 | mask = El _
 47 |
 48 | export %inline
 49 | rect : List (SVGAttribute "rect") -> SVGNode
 50 | rect = el _
 51 |
 52 | export %inline
 53 | path : List (SVGAttribute "path") -> SVGNode
 54 | path = el _
 55 |
 56 | export %inline
 57 | polygon : List (SVGAttribute "polygon") -> SVGNode
 58 | polygon = el _
 59 |
 60 | export %inline
 61 | polyline : List (SVGAttribute "polyline") -> SVGNode
 62 | polyline = el _
 63 |
 64 | export %inline
 65 | svg : List (SVGAttribute "svg") -> List SVGNode -> SVGNode
 66 | svg = El _
 67 |
 68 | export %inline
 69 | symbol : List (SVGAttribute "symbol") -> List SVGNode -> SVGNode
 70 | symbol = El _
 71 |
 72 | export %inline
 73 | text1 : List (SVGAttribute "text") -> String -> SVGNode
 74 | text1 as s = El _ as [Txt s]
 75 |
 76 | export %inline
 77 | text : List (SVGAttribute "text") -> List SVGNode -> SVGNode
 78 | text as = El _ as
 79 |
 80 | export %inline
 81 | tspan : List (SVGAttribute "tspan") -> List SVGNode -> SVGNode
 82 | tspan as = El _ as
 83 |
 84 | export %inline
 85 | use : List (SVGAttribute "use") -> SVGNode
 86 | use = el _
 87 |
 88 | export %inline
 89 | view : List (SVGAttribute "view") -> SVGNode
 90 | view = el _
 91 |
 92 | --------------------------------------------------------------------------------
 93 | -- Render
 94 | --------------------------------------------------------------------------------
 95 |
 96 | export
 97 | escape : String -> String
 98 | escape = fastConcat . map esc . unpack
 99 |
100 |   where
101 |     esc : Char -> String
102 |     esc '<'          = "&lt;"
103 |     esc '>'          = "&gt;"
104 |     esc '&'          = "&amp;"
105 |     esc '"'          = "&quot;"
106 |     esc '\''         = "&#x27"
107 |     esc '\n'         = "\n"
108 |     esc '\r'         = "\r"
109 |     esc '\t'         = "\t"
110 |     esc c            = if c < ' ' then "" else singleton c
111 |
112 | attrs : {0 t : _} -> List (SVGAttribute t) -> String
113 | attrs as = let s = displayAttributes as in if null s then "" else " " ++ s
114 |
115 | export
116 | render : SVGNode -> String
117 | render n = case n of
118 |   Raw x         => x
119 |   Txt x         => escape x
120 |   El tag as []  => "<\{tag}\{attrs as}/>"
121 |   El tag as ns  => "<\{tag}\{attrs as}>\{go [<] ns}</\{tag}>"
122 |   Empty         => ""
123 |
124 |   where
125 |     go : SnocList String -> List SVGNode -> String
126 |     go ss (n :: ns) = go (ss :< render n) ns
127 |     go ss []        = concat $ ss <>> []
128 |
129 | export
130 | renderMany : List SVGNode -> String
131 | renderMany = fastConcat . map render
132 |