6fb939a3b5bdde4c7e1a5833f115c2b9f6111719
[wix.git] / src / Html.lhs
1 \begin{code}
2 module Html
3 where
4 import Edu_Berkeley_Sbp_Haskell_SBP
5 import FromTree
6 import Doc
7 import List(isSuffixOf,isPrefixOf)
8
9 -- FIXME: use pretty-printing when asked to for better display
10
11 class ToHtml a where
12   toHtml :: a -> String
13 instance ToHtml a => ToHtml [a] where
14   toHtml x = concatMap toHtml x
15
16 style =
17   "\n<style>\n"++
18   " h1, h2, h3, h4 { font-family: 'Trebuchet MS', arial, verdana, sans-serif; width: 100% }\n"++
19   " h1 { font-size: 20pt; border-top: black 1px solid; }\n"++
20   " h2 { font-size: 16pt; border-top: silver 1px solid; }\n"++
21   " h3 { font-size: 12pt; }\n"++
22   " TH, TD, P, LI, DIV, SPAN {\n"++
23   "     font-family: verdana, arial, sans-serif;\n"++
24   "     font-size: 12px;  \n"++
25   "     text-decoration:none; \n"++
26   " }\n"++
27   " LI { margin-top: 5px; }\n"++
28   " body { color: #333333; }\n"++
29   " blockquote { font-style: italic; width: 100% }\n"++
30   " div.warn { border: 1px solid red; background-color: #fbb; color: white; }\n"++
31   " td.warn { color: black; }\n"++
32   " div.announce { border: 1px solid green; background-color: #bfb; color: white; }\n"++
33   " td.announce { color: black; }\n"++
34   " div.footer {\n"++
35   "   color: gray;\n"++
36   "   border-top: 1px solid silver;\n"++
37   "   font-size: 10px;\n"++
38   " }\n"++
39   " table.blockquote { margin: 5px; border: 1px #e6ddcb solid; background-color: #fbf2e0; width: 100% }\n"++
40   " a:link { text-decoration: none; color: blue; border-bottom:1px dotted; }\n"++
41   " a:visited { text-decoration: none; color: purple; border-bottom:1px dotted; }\n"++
42   " a:active { text-decoration: none; color: red; border-bottom:1px solid; }\n"++
43   " a:hover { text-decoration: none; border-bottom:1px solid; }\n"++
44   " table.footer { border-top: silver solid 1px; }\n"++
45   " span.signature { color: #bbb;  }\n"++
46   " .signature a:link { color: #bbb;  }\n"++
47   " .signature a:visited { color: #bbb;  }\n"++
48   " .signature a:hover { color: blue; border-bottom: 1px solid blue;  }\n"++
49   " span.highlight { background: yellow; color: black; padding: 3px }\n"++
50   " div.pre {\n"++
51   "     text-align: left;\n"++
52   "     font-family: monospace;\n"++
53   "     border-style: solid;\n"++
54   "     border-width: 2px 2px 2px 2px;\n"++
55   "     border-color: #6666aa;\n"++
56   "     color: #FFFFFF;\n"++
57   "     background-color: #000000;\n"++
58   "     margin-right: 25px;\n"++
59   "     margin-left: 25px;\n"++
60   "     padding: 10px;\n"++
61   "  }\n"++
62   "</style>\n"
63   
64
65 instance ToHtml Doc where
66  toHtml (Doc h secs) =
67      "<!-- This document was AUTOMATICALLY GENERATED from wix source -->\n"++
68      "<!--    it is probably not a wise idea to edit it directly     -->\n\n"++
69      "<html>\n"++
70      "<head>\n"++
71      style++
72      --FIXME: title tag
73      "</head>\n"++
74      "<body>\n"++   -- tell jsmath we will escape stuff manually
75
76      -- FIXME: only put this in if math appears on the page
77      "<script> jsMath = { showFontWarnings: false } </script>\n"++
78      "<script src='/jsmath/easy/load.js'></script>\n"++
79      "<span id='tex2math_off'></span>\n"++
80      "<NOSCRIPT> <DIV STYLE='color:#CC0000; text-align:center'> <B>Warning: <A HREF='http://www.math.union.edu/locate/jsMath'>jsMath</A> requires JavaScript to process the mathematics on this page.<BR> If your browser supports JavaScript, be sure it is enabled.</B> </DIV> <HR> </NOSCRIPT>\n"++
81
82      "<center><table><tr><td width=600>\n"++
83      (toHtml secs) ++
84      "<br><br>\n"++
85      "<table width=100% class=footer><tr><td align=left>"++
86      "<img src='"++printIconBase64++"'></td>"++
87      "<td align=right><span class='signature'>rendered from "++
88      "<a href=http://www.megacz.com/software/wix>"++
89      "W<span style='vertical-align:-20%'>I</span>X</a></span></div></td></tr></table>\n"++
90      "</td></tr></table></center>\n"++
91      "</body></html>"
92
93 quoteIconBase64 = 
94     "data:image/png;base64,"
95     ++"iVBORw0KGgoAAAANSUhEUgAAABAAAAAVCAYAAABPPm7SAAAABmJLR0QA/wD/AP+gvaeTAAAA"
96     ++"CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wQPAx0rP5obpAAAAWJJREFUOMvdlKFvg0AU"
97     ++"xr8tVZ1cbU+04lUuwc2WypMX9AxiomoJ/RNYqmaaYKpb5kBys1UkWBCdKLqVs8zwFnrQmYol"
98     ++"+xLC8X55H/e+wAENhWGoPM/zT6eThQ4lSWJf5EEQuAAqAJXv+95vXCkVtpwZuq4bmM1pmlrM"
99     ++"LctKWzuwbTsBUNX3lph3Njfd6/WZ9vv9iHkYhsrkPa21zQ9aa9v3fRsAFovFK9cMPgIApdT7"
100     ++"eDz+RB1Y1XEBwEVe54ZbXKm/N7haNwCQ5zmtVqtnE0op49lspgFgPp+/dfF/EGIPAAaDgZBS"
101     ++"xgBwPB7vd7vdIwD0+/2v5ry8juNYmgY/P1GWZQ9sQER3XOcwD4fDkA2IqGiNwN8+ERVNY/Pt"
102     ++"RFQIIcozg+Vy+VKW5dDcMmuz2ThFURAATKfTj7MQ1+v1Ezc7jrMVQpTmocOjOY6znUwmRSvR"
103     ++"KIpknud0KfEoimSWZQ/N2jfhtb1AvGklDQAAAABJRU5ErkJggg=="
104
105 warnIconBase64 = 
106     "data:image/png;base64,"
107     ++"iVBORw0KGgoAAAANSUhEUgAAABQAAAAREAYAAACN1FD9AAAABmJLR0QA/wD/AP+gvaeTAAAA"
108     ++"CXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAUAAAAEQDeTN6UAAAD/ElEQVRIx8WUbUyV"
109     ++"ZRjHf+chxDi8yZcDa0mKh/wSuNE5eNYHZBiRwoespayEkdgx22hmjB1glTlenDYlMccAX1cb"
110     ++"CDFlg+aQ1JGEazGWpixdbbweDucctPF2PNxXX3pw00gL09+X59m1+77+v+d+nueCBRJ+ECAs"
111     ++"78dnAPp2nLEDtMdpPwMYZhfaf8GU1gLsixwdBRDRr7lRAHmxT0zs+UKAuKmhXgDfGleAYZVh"
112     ++"lXynC/Z1AYyeX+IFiLjw+MwWAxDQuBqgNVsX+iNta/nWcnV0vD+9Ir1CndDre68AfDH42PzW"
113     ++"2QDW79UFxkxh6WHp8o5a5lznXCfJ/nPX867nSYArO7AssEyOjOwE8GfGZwC84Pu3edrDLgzK"
114     ++"AFj06q7DAPt/1evBK4szizMlpXy4tqO2g/MHa9sm2ibwP23M78zvFE0rBAg4U24DqFpieAqA"
115     ++"6kd+cjuiAAqu6Sfn/n55/fJ6CZOc6YHpATmkNWgNWoOIZtSMmlFE1d9ae2utvDt21ZRiSpHV"
116     ++"+r43LwFkBT4ysehigKgDvxcC3P5QD5qxNtU11anj8hfhg+GD4YMixipjlbFK5pjyHok8Enn3"
117     ++"m7yyG2DAEdIFYLy9YMHDLoBjK/WA8fhkb7JXtcqMnJbT4tJFYlpiWmJaRKJio2KjYu8KSp9K"
118     ++"UAly2ZtpSbWkql/0PrsuAJR3/2cx65cA1qujRgBV6HpWy9fy5dydOz2JPYlqQO4hwZ/gT/CL"
119     ++"mB1mh9kh93Enq2tP1x7V4wo0pBnS5KehVwBmPjA7AcxtDy2mBQIYPmk/B/CDb26MxGw5teWU"
120     ++"+krmIdWaak21iiR2JHYkdsi83G7KtmRb1HG9b+PHAK2lJAEQ9EDBt88C5BybGyOLQgtCC8Su"
121     ++"gkesI1axzRd8Mvdk7slckeoN1RuqN8wvODsyVDNUIxaXP0SFKHlfz8l4GSDTfd+B6Tdh5QCh"
122     ++"hUUvAlR8o9eDI4qSipLkJcOEqdvUzaX5HmzSNGmaNMFN+037TTvgxInzb96QKTovOo/LRmuJ"
123     ++"r8QnFr3+2esAB/IX9wAEjd+3cfc+gD2euTFSv2zzss0SIdnTG6c3SqU8AFulrdJWKRJSElIS"
124     ++"UiLia/Y1+5r/YcNHM9tntku1e2KFZ4VHAvXcwnyAksY5MfNvAOYdQ+8BzHytL5warDtRd2I2"
125     ++"QjWNh46HqjR11LvGu0aVqUOei56LYlD7PRWeCmlWpe4p95R87h66Yb9hV+7+o71BvUHKoWyj"
126     ++"jlGHSlbPOTc5N6kkFTqybWSbeksxfHb4rGqd9Q3nDOdI5lRHTXtNu6rWc/vfAJjoXHoNYOl6"
127     ++"Q70CaFEpYwAZhof+m/5nvv0UoDFLW/UagCXuSQvdSzwAiTv/BGXg1AxNKyCeAAAAAElFTkSu"
128     ++"QmCC"
129
130 printIconBase64 = 
131     "data:image/png;base64,"
132     ++"iVBORw0KGgoAAAANSUhEUgAAAA8AAAAOCAMAAADHVLbdAAAALHRFWHRDcmVhdGlvbiBUaW1l"
133     ++"AEZyaSAxOSBTZXAgMjAwMyAxODozOTozMiAtMDAwME2jAt8AAAAHdElNRQfTCRMRKABXeznM"
134     ++"AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAACRQTFRF////AAAA7+/v"
135     ++"3t7ezs7OtbW1ra2tlJSUnJycEBAQKSkphISEbGtEogAAAAF0Uk5TAEDm2GYAAABLSURBVHja"
136     ++"nY1BEsAgCAMDKm31//81qB3l6h4Y4mYQQNvAmXNv7W/gytcTRj6pppQHNWoW6JWS13Ix86yr"
137     ++"O7MEPkDWuWLPK/7hoYEOxksDsk8eppEAAAAASUVORK5CYII="
138
139
140 emailIconBase64 =
141     "data:image/png;base64,"
142     ++"iVBORw0KGgoAAAANSUhEUgAAABUAAAAOCAMAAAD32Kf8AAAALHRFWHRDcmVhdGlvbiBUaW1l"
143     ++"AEZyaSAxOSBTZXAgMjAwMyAxODo0MjowOSAtMDAwMBDwv7IAAAAHdElNRQfTCRMRKhqYL6I0"
144     ++"AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAADBQTFRF////AAAAhISE"
145     ++"9/fv9/f3////CAgI7+/v1tbOxsa9tbWtpaWclJSMlJSUe3t7a2trxDv8WgAAAAF0Uk5TAEDm"
146     ++"2GYAAABiSURBVHjabc9JEoAgDETRpNOKs/e/rSEYF8jfhHpQFAi6JHpHBg5VOdIj+KeXkgO9"
147     ++"tUj/Bldo3WdRnktt3fbjgoWKK5EKsunkyryCn86Oxsj/UZqKEkFmNF+mvieFdSK16wFr7QK5"
148     ++"tASqkwAAAABJRU5ErkJggg=="
149
150 pdfIconBase64 = 
151     "data:image/png;base64,"
152     ++"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAK3RFWHRDcmVhdGlvbiBUaW1l"
153     ++"AFRodSA2IE5vdiAyMDAzIDE1OjMwOjAwIC0wMDAwSwt8PwAAAAd0SU1FB9MLBg8fD1x8/t4A"
154     ++"AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAEZ0FNQQAAsY8L/GEFAAAAQlBMVEX///9zc3Nra2uE"
155     ++"hITGxsaUlJScnJx7e3uMjIz////39/fv7+/n5+fe3t69vb1jY2OlpaXW1ta1tbVaWlqtra3O"
156     ++"zs5w48BYAAAAAXRSTlMAQObYZgAAAIdJREFUeNpNz1ESBBEMBNCRwSCJMOT+V10WW9vKz6uO"
157     ++"iusa0R137ShxjImwHsnSMCbEX6dPiIje+SUKC6hav8CbAQlZD/RmJ1Tdz6oTwETMfAByK0hT"
158     ++"1kgH7E1phFfjdvS2JlJpN8RAyEHMhgJgaexJTBPyA1JiGoD0BXgg2H8wcFs3/jDvPB+sOwir"
159     ++"+o6iKQAAAABJRU5ErkJggg=="
160
161 instance ToHtml Section where
162  toHtml (Section level header paragraphs) =
163      "\n<h"++(show (level+1))++">\n"++
164      (toHtml header)++
165      "\n</h"++(show (level+1))++">\n"++
166      (toHtml paragraphs)
167 stag t body = "\n<"++t++">\n"++body++"\n</"++t++">\n"
168 tag  t body = "<"++t++">"++body++"</"++t++">"
169
170 instance ToHtml Paragraph where
171  toHtml (Blockquote t) = "\n<table class=blockquote border=0 cellpadding=5px>\n"
172                          ++"<tr><td valign=top><image src='"++quoteIconBase64++"'></td>\n"
173                          ++"<td class=warn>\n"
174                          ++(toHtml t)
175                          ++"</td></tr></table>\n"
176  toHtml HR             = stag "hr" []
177  toHtml (OL t)         = stag "ol" $ concatMap (\x -> stag "li" $ concatMap toHtml x) t
178  toHtml (UL t)         = stag "ul" $ concatMap (\x -> stag "li" $ concatMap toHtml x) t
179  toHtml (P t)          = stag "p"  $ toHtml t
180
181
182 link ref body = "<a href='"++ref++"'>"++icon++body++"</a>"
183  where
184   icon = if      ".pdf" `isSuffixOf` ref then "<img "++img++" src='"++pdfIconBase64++"'>&nbsp;"
185          else if "mailto:" `isPrefixOf` ref then "<img "++img++" src='"++emailIconBase64++"'>&nbsp;"
186          else ""
187   img = "style='vertical-align: text-bottom;' border=0 "
188 -- margin-bottom: -2px; padding-bottom: 2px;  border-bottom: 1px blue solid;
189
190 instance ToHtml Text where
191  toHtml WS                        = " "
192  toHtml (Chars s)                 = toHtml s
193   
194  -- directional quotes: see http://www.dwheeler.com/essays/quotes-in-html.html
195  toHtml (Quotes x)                = "&#8220;"++(toHtml x)++"&#8221;"
196  toHtml (Verbatim x)              = pre x
197  toHtml (Link t ref)              = link (show ref) (toHtml t)
198  toHtml (Command "url" y)         = "<tt>"++(link (toHtml y) (toHtml y))++"</tt>"
199  toHtml (Command "WiX" y)         = "W<span style='vertical-align:-20%'>I</span>X"
200  toHtml (Command "TeX" y)         = "T<span style='vertical-align:-20%'>E</span>X"
201 --   u'1/2' : u'\u00BD',
202 --    u'1/4' : u'\u00BC',
203 --    u'3/4' : u'\u00BE',
204 --    u'1/3' : u'\u2153',
205 --    u'2/3' : u'\u2154',
206 --    u'1/5' : u'\u2155',
207 --    u'2/5' : u'\u2156',
208 --    u'3/5' : u'\u2157',
209 --    u'4/5' : u'\u2158',
210 --    u'1/6' : u'\u2159',
211 --    u'5/6' : u'\u215A',
212 --    u'1/8' : u'\u215B',
213 --    u'3/8' : u'\u215C',
214 --    u'5/8' : u'\u215D',
215 --    u'7/8' : u'\u215E',
216
217  toHtml (Styled Underline x)      = tag "u" $ toHtml x
218  toHtml (Styled TT x)             = tag "tt" $ toHtml x
219  toHtml (Styled Italic x)         = tag "i" $ toHtml x
220  toHtml (Styled Strikethrough x)  = tag "strike" $ toHtml x
221  toHtml (Styled Superscript x)    = tag "sup" $ toHtml x
222  toHtml (Styled Subscript x)      = tag "sub" $ toHtml x
223  toHtml (Styled Bold x)           = tag "b" $ toHtml x
224  toHtml (Styled Highlight x)      = "<span class=highlight>"++(toHtml x)++"</span>"
225
226  toHtml (Keyword x)               = tag "tt" $ toHtml x
227  toHtml (SubPar x)                = stag "p" $ concatMap toHtml x
228
229  toHtml (Command "red" y)         = "<font color=red>"++(toHtml y)++"</font>"
230  toHtml (Command "orange" y)      = "<font color=orange>"++(toHtml y)++"</font>"
231  toHtml (Command "green" y)       = "<font color=green>"++(toHtml y)++"</font>"
232  toHtml (Command "sc" y)          = "<sc>"++(toHtml y)++"</sc>"
233  toHtml (Command "image" y)       = "<img src='"++(toHtml y)++"'/>"
234  toHtml (Command "image3" y)      = "<img width=200px src='"++(toHtml y)++"'/>"
235  toHtml (Command "image4" y)      = "<center><img width=550px src='"++(toHtml y)++"'/></center>"
236  toHtml (Command "warn" y)        = "\n<div class=warn>\n<table border=0 cellpadding=5px>\n"
237                                     ++"<tr><td valign=top><image src='"++warnIconBase64++"'></td>\n"
238                                     ++"<td class=warn>\n"
239                                     ++(toHtml y)
240                                     ++"</td></tr></table></div>\n"
241  toHtml (Command "announce" y)    = "\n<div class=announce>\n<table border=0 cellpadding=5px>\n"
242                                     ++"<tr><td valign=top></td>\n"
243                                     ++"<td class=warn>\n"
244                                     ++(toHtml y)
245                                     ++"</td></tr></table></div>\n"
246  toHtml (Command "br" _)          = "\n<br/>\n"
247  toHtml (Command "cent" _)        = "&#189;"
248  toHtml (Command "euro" _)        = "&#8364;"
249  toHtml (Command "ordinal" x)      = (toHtml x)++"<sup>"++"th"++"</sup>"
250  -- FIXME: use "unicode vulgar fractions" here
251  toHtml (Command "fraction" [n,d]) = "<sup>"++(toHtml n)++"</sup>"++"/"++"<sub>"++(toHtml d)++"</sub>"
252  toHtml (Command "rfc" x)         = "<tt><a href=http://tools.ietf.org/html/rfc"++(toHtml x)++">RFC"++(toHtml x)++"</a></tt>"
253
254  -- FIXME: add div as well (for display-mode math)
255  toHtml (Math m)                  = "<span class=math>" ++ (toHtml m) ++ "</span>"
256  toHtml (Footnote x)              = error $ "footnotes not supported"
257
258  toHtml (GlyphText Euro)          = "&#8364;"
259  toHtml (GlyphText CircleR)       = "&#162;"
260  toHtml (GlyphText CircleC)       = "&#174;"
261  toHtml (GlyphText TradeMark)     = "&#8482;"
262  toHtml (GlyphText ServiceMark)   = "&#8482;"
263  toHtml (GlyphText Emdash)        = "&mdash;"
264  toHtml (GlyphText Ellipsis)      = "&#0133;"
265  toHtml (GlyphText Cent)          = "&#189;"
266  toHtml (GlyphText Daggar)        = "&#8224;"
267  toHtml (GlyphText DoubleDaggar)  = "&#8225;"
268  toHtml (GlyphText Clover)        = "&#8984;"
269  toHtml (GlyphText Flat)          = "&#8918;"
270  toHtml (GlyphText Natural)       = "&#8919;"
271  toHtml (GlyphText Sharp)         = "&#8920;"
272  toHtml (GlyphText CheckMark)     = "&#10003;"
273  toHtml (GlyphText XMark)         = "&#10007;"
274  toHtml (GlyphText LeftArrow)            = "&#;"  -- FIXME
275  toHtml (GlyphText DoubleLeftArrow)      = "&#;"  -- FIXME
276  toHtml (GlyphText DoubleRightArrow)     = "&#;"  -- FIXME
277  toHtml (GlyphText DoubleLeftRightArrow) = "&#;"  -- FIXME
278  toHtml (GlyphText LeftRightArrow)       = "&#;"  -- FIXME
279  toHtml (GlyphText Degree)               = "&#;"  -- FIXME
280
281  toHtml (Command ('k':'e':'y':'s':'t':'r':'o':'k':'e':':':k) _) =
282      "&#x"++(case k of
283                "command" -> "2318"
284                "shift" -> "21E7"
285                "option" -> "2325"
286                "control" -> "2303"
287                "capslock" -> "21EA"
288                "apple" -> "F8FF"
289                )++";"
290  toHtml (Command x y)             = error $ "unsupported command "++(show x)
291
292 instance ToHtml String where
293   toHtml s = concatMap htmlEscapeChar s
294
295 htmlEscapeChar '<'  = "&lt;"
296 htmlEscapeChar '>'  = "&gt;"
297 htmlEscapeChar '&'  = "&amp;"
298 htmlEscapeChar '\'' = "&apos;"
299 htmlEscapeChar '\"' = "&quot;"
300 htmlEscapeChar c    = [c]
301
302 pre x = "\n<div class=pre>"++ (pre' x) ++ "\n</div>\n"
303  where
304   pre' (' ':b)         = "&nbsp;"++(pre' b)
305   pre' ('\n':b)        = "<br/>\n"++(pre' b)
306   pre' (a:b)           = (htmlEscapeChar a)++(pre' b)
307   pre' []              = []
308 \end{code}