1 ! Copyright (C) 2004, 2009 Slava Pestov.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs colors combinators destructors html io
4 io.styles kernel make math math.functions math.parser sequences
8 GENERIC: url-of ( object -- url )
10 M: object url-of drop f ;
12 TUPLE: html-writer data ;
13 INSTANCE: html-writer output-stream
17 : new-html-writer ( class -- html-writer )
18 new V{ } clone >>data ; inline
20 TUPLE: html-sub-stream < html-writer style parent ;
22 : new-html-sub-stream ( style stream class -- stream )
27 : end-sub-stream ( substream -- string style stream )
28 [ data>> ] [ style>> ] [ parent>> ] tri ;
30 : object-link-tag ( xml style -- xml )
31 presented of [ url-of [ simple-link ] when* ] when* ;
33 : href-link-tag ( xml style -- xml )
34 href of [ simple-link ] when* ;
36 : fg-css, ( color -- )
37 "color: " % color>hex % "; " % ;
39 : bg-css, ( color -- )
40 "background-color: " % color>hex % "; " % ;
42 : style-css, ( flag -- )
44 { italic bold-italic } member?
45 "font-style: " % "italic" "normal" ? % "; " %
46 { bold bold-italic } member?
47 "font-weight: " % "bold" "normal" ? % "; " % ;
49 : size-css, ( size -- )
50 "font-size: " % # "pt; " % ;
52 : font-css, ( font -- )
53 "font-family: " % % "; " % ;
55 MACRO: make-css ( pairs -- str )
56 [ '[ _ of [ _ execute ] when* ] ] { } assoc>map
57 '[ [ _ cleave ] "" make ] ;
59 : span-css-style ( style -- str )
61 { foreground fg-css, }
62 { background bg-css, }
63 { font-name font-css, }
64 { font-style style-css, }
65 { font-size size-css, }
68 : span-tag ( xml style -- xml )
70 [ swap [XML <span style=<->><-></span> XML] ] unless-empty ; inline
72 : emit-html ( stream quot -- )
73 dip data>> push ; inline
75 : img-tag ( xml style -- xml )
76 image-style of [ nip simple-image ] when* ;
78 : format-html-span ( string style stream -- )
88 TUPLE: html-span-stream < html-sub-stream ;
90 M: html-span-stream dispose
91 end-sub-stream format-html-span ;
93 : border-css, ( border -- )
94 "border: 1px solid " % color>hex % "; " % ;
96 : (padding-css,) ( horizontal vertical -- )
98 drop "padding: " % # "px; " %
100 "padding: " % # "px " % # "px; " %
103 : padding-css, ( padding -- )
104 first2 (padding-css,) ;
106 : width-css, ( width -- )
107 "width: " % # "px; " % ;
109 : div-css-style ( style -- str )
113 { page-color bg-css, }
114 { border-color border-css, }
115 { inset padding-css, }
116 { wrap-margin width-css, }
118 ] bi "display: inline-block; " 3append ;
120 : div-tag ( xml style -- xml' )
122 [ swap [XML <div style=<->><-></div> XML] ] unless-empty ;
124 : format-html-div ( string style stream -- )
125 [ [ div-tag ] [ object-link-tag ] bi ] emit-html ;
127 TUPLE: html-block-stream < html-sub-stream ;
129 M: html-block-stream dispose
130 end-sub-stream format-html-div ;
132 : border-spacing-css, ( pair -- )
133 first2 [ 2 /i ] bi@ (padding-css,) ;
135 : table-style ( style -- str )
137 { table-border border-css, }
138 { table-gap border-spacing-css, }
144 M: html-writer stream-flush drop ;
146 M: html-writer stream-write1
147 [ 1string ] emit-html ;
149 M: html-writer stream-write
152 M: html-writer stream-format
155 M: html-writer stream-nl
156 [ [XML <br/> XML] ] emit-html ;
158 M: html-writer make-span-stream
159 html-span-stream new-html-sub-stream ;
161 M: html-writer make-block-stream
162 html-block-stream new-html-sub-stream ;
164 M: html-writer make-cell-stream
165 html-sub-stream new-html-sub-stream ;
167 M: html-writer stream-write-table
170 [ data>> [XML <td valign="top" style=<->><-></td> XML] ] with map
171 [XML <tr><-></tr> XML]
173 [XML <table style="display: inline-table; border-collapse: collapse;"><-></table> XML]
176 M: html-writer dispose drop ;
178 : <html-writer> ( -- html-writer )
179 html-writer new-html-writer ;
181 : with-html-writer ( quot -- xml )
182 <html-writer> [ swap with-output-stream* ] keep data>> ; inline