1 ! Copyright (C) 2004, 2006 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: callback-responder generic hashtables help http tools
4 io kernel math namespaces prototype-js sequences strings styles
8 : hex-color, ( triplet -- )
10 [ 255 * >fixnum >hex 2 CHAR: 0 pad-left % ] each ;
12 : fg-css, ( color -- )
13 "color: #" % hex-color, "; " % ;
15 : bg-css, ( color -- )
16 "background-color: #" % hex-color, "; " % ;
18 : style-css, ( flag -- )
20 { italic bold-italic } member?
21 "font-style: " % "italic" "normal" ? % "; " %
22 { bold bold-italic } member?
23 "font-weight: " % "bold" "normal" ? % "; " % ;
25 : size-css, ( size -- )
26 "font-size: " % # "pt; " % ;
28 : font-css, ( font -- )
29 "font-family: " % % "; " % ;
31 : hash-apply ( value-hash quot-hash -- )
32 #! Looks up the key of each pair in the first list in the
33 #! second list to produce a quotation. The quotation is
34 #! applied to the value of the pair. If there is no
35 #! corresponding quotation, the value is popped off the
38 swap rot hash dup [ call ] [ 2drop ] if
41 : span-css-style ( style -- str )
44 { foreground [ fg-css, ] }
45 { background [ bg-css, ] }
46 { font [ font-css, ] }
47 { font-style [ style-css, ] }
48 { font-size [ size-css, ] }
52 : span-tag ( style quot -- )
53 over span-css-style dup empty? [
56 <span =style span> call </span>
59 : border-css, ( border -- )
60 "border: 1px solid #" % hex-color, "; " % ;
62 : padding-css, ( padding -- ) "padding: " % # "px; " % ;
65 "white-space: pre; font-family:monospace; " % ;
67 : div-css-style ( style -- str )
70 { page-color [ bg-css, ] }
71 { border-color [ border-css, ] }
72 { border-width [ padding-css, ] }
73 { wrap-margin [ [ pre-css, ] unless ] }
77 : div-tag ( style quot -- )
78 swap div-css-style dup empty? [
81 <div =style div> call </div>
84 : do-escaping ( string style -- string )
85 html swap hash [ chars>entities ] unless ;
87 GENERIC: browser-link-href ( presented -- href )
89 M: object browser-link-href drop f ;
91 : resolve-file-link ( path -- link )
92 #! The file responder needs relative links not absolute
95 ?head [ "/" ?head drop ] when
96 ] when* "/" ?tail drop ;
98 M: pathname browser-link-href
100 "/" swap resolve-file-link url-encode append ;
102 : object-link-tag ( style quot -- )
103 presented pick hash browser-link-href
104 [ <a =href a> call </a> ] [ call ] if* ;
106 TUPLE: nested-stream ;
108 C: nested-stream [ set-delegate ] keep ;
110 M: nested-stream stream-close drop ;
114 C: html-stream ( stream -- stream ) [ set-delegate ] keep ;
116 M: html-stream stream-write1 ( char stream -- )
117 >r ch>string r> stream-write ;
119 : delegate-write delegate stream-write ;
121 M: html-stream stream-write ( str stream -- )
122 >r chars>entities r> delegate-write ;
124 : with-html-style ( quot style stream -- )
125 [ [ swap span-tag ] object-link-tag ] with-stream* ; inline
127 M: html-stream with-stream-style ( quot style stream -- )
128 [ drop call ] -rot with-html-style ;
130 M: html-stream stream-format ( str style stream -- )
131 [ do-escaping stdio get delegate-write ] -rot
134 : with-html-stream ( quot -- )
135 stdio get <html-stream> swap with-stream* ;
139 <div "padding-left: 20px; " =style div>
144 : html-outliner ( caption contents -- )
145 "+ " get-random-id dup >r
146 rot make-outliner-quot updating-anchor call
147 <span r> =id "display: none; " =style span> </span> ;
149 : outliner-tag ( style quot -- )
150 outline pick hash [ html-outliner ] [ call ] if* ;
152 M: html-stream with-nested-stream ( quot style stream -- )
157 stdio get <nested-stream> swap with-stream*
163 : border-spacing-css,
164 "padding: " % first2 max 2 /i # "px; " % ;
166 : table-style ( style -- str )
169 { table-border [ border-css, ] }
170 { table-gap [ border-spacing-css, ] }
174 : table-attrs ( style -- )
175 table-style " border-collapse: collapse;" append =style ;
177 M: html-stream with-stream-table ( grid quot style stream -- )
179 <table dup table-attrs table> rot [
181 <td "top" =valign over table-style =style td>
182 pick H{ } swap with-nesting
185 ] each 2drop </table>
188 M: html-stream stream-terpri [ <br/> ] with-stream* ;
191 <style "text/css" =type style>
192 "a:link { text-decoration: none; color: black; }" print
193 "a:visited { text-decoration: none; color: black; }" print
194 "a:active { text-decoration: none; color: black; }" print
195 "a:hover, A:hover { text-decoration: underline; color: black; }" print
200 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" print ;
202 : html-document ( title quot -- )
205 <html " xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"" write html>
207 <title> write </title>
216 : simple-html-document ( title quot -- )
217 swap [ <pre> with-html-stream </pre> ] html-document ;