| 1 |
abate |
284 |
(* This CDuce script produces CDuce web site. *) |
| 2 |
|
|
|
| 3 |
abate |
343 |
(** Output types **) |
| 4 |
abate |
284 |
|
| 5 |
abate |
258 |
include "xhtml-strict.cd";; (* XHTML 1 Strict DTD *) |
| 6 |
|
|
include "xhtml-categ.cd";; (* Categories (Inline, ...) from this DTD *) |
| 7 |
abate |
250 |
|
| 8 |
abate |
336 |
|
| 9 |
abate |
343 |
(** Input types **) |
| 10 |
|
|
|
| 11 |
|
|
type Page = <page name=String>[ <title>String <banner>[InlineText*] Item* ];; |
| 12 |
|
|
type External = <external {|href=String; title=String; name=String |}>[];; |
| 13 |
|
|
|
| 14 |
|
|
type Item = |
| 15 |
|
|
<box title=String; subtitle=?String; link=String>Content |
| 16 |
|
|
| <meta>Content |
| 17 |
|
|
| <left>Content |
| 18 |
|
|
| Page |
| 19 |
|
|
| External;; |
| 20 |
|
|
|
| 21 |
|
|
type Author = <author>String;; |
| 22 |
|
|
type Paper = |
| 23 |
|
|
<paper file=?String>[ |
| 24 |
|
|
<title>String Author+ <comment>[InlineText*] <abstract>Content ];; |
| 25 |
|
|
|
| 26 |
|
|
type Slides = |
| 27 |
|
|
<slides file=String>[ <title>String Author+ <comment>[InlineText*] ];; |
| 28 |
|
|
|
| 29 |
|
|
type Link = |
| 30 |
|
|
<link url=String; title=String>[ InlineText* ];; |
| 31 |
|
|
|
| 32 |
|
|
type Content = |
| 33 |
|
|
[ ( <p {||}>[InlineText*] |
| 34 |
|
|
| <ul {||}>[<li {||}>Content +] |
| 35 |
|
|
| <section title=String>Content |
| 36 |
abate |
344 |
| <sample highlight=?"true"|"false">String |
| 37 |
abate |
343 |
| Xtable |
| 38 |
|
|
| Paper | Slides | Link |
| 39 |
|
|
| <boxes-toc>[] |
| 40 |
|
|
| <pages-toc>[] |
| 41 |
|
|
| <site-toc>[] |
| 42 |
|
|
| <local-links href=String>[] |
| 43 |
|
|
| InlineText |
| 44 |
|
|
)* ];; |
| 45 |
|
|
|
| 46 |
|
|
type InlineText = |
| 47 |
|
|
Char |
| 48 |
|
|
| <(`b|`i|`tt|`em) {||}>[InlineText*] |
| 49 |
|
|
| <code>String |
| 50 |
abate |
347 |
| <local href=String>String |
| 51 |
abate |
343 |
| Xa | Ximg | Xbr ;; |
| 52 |
|
|
|
| 53 |
|
|
|
| 54 |
|
|
(** Generic purpose functions **) |
| 55 |
|
|
|
| 56 |
|
|
(* Recursive inclusion of XML files and verbatim text files *) |
| 57 |
|
|
|
| 58 |
abate |
336 |
let fun load_include (String -> [Any*]) |
| 59 |
|
|
name -> |
| 60 |
|
|
let _ = print [ 'Loading ' !name '... \n' ] in |
| 61 |
|
|
xtransform [ (load_xml name) ] with |
| 62 |
abate |
341 |
| <include file=(s & String)>[] -> load_include s |
| 63 |
|
|
| <include-verbatim file=(s & String)>[] -> load_file s;; |
| 64 |
abate |
336 |
|
| 65 |
abate |
343 |
(* Highlighting text between {{...}} *) |
| 66 |
abate |
336 |
|
| 67 |
abate |
340 |
let fun highlight (String -> [ (Char | Xvar)* ] ) |
| 68 |
|
|
| [ '{{' h ::(Char *?) '}}' ; rest ] -> |
| 69 |
|
|
[ <var class="highlight">h; highlight rest ] |
| 70 |
|
|
| [ c; rest ] -> [ c; highlight rest ] |
| 71 |
abate |
336 |
| [] -> [];; |
| 72 |
|
|
|
| 73 |
abate |
343 |
(* Split a comma-separated string *) |
| 74 |
|
|
|
| 75 |
abate |
341 |
let fun split_comma (String -> [String*]) |
| 76 |
|
|
| [ x::(Char*?) ',' ; rest ] -> (x, split_comma rest) |
| 77 |
|
|
| s -> [ s ];; |
| 78 |
abate |
336 |
|
| 79 |
abate |
253 |
|
| 80 |
abate |
343 |
(** Ugly hack to introduce PHP code ... |
| 81 |
|
|
The idea is to produce first an XML document with a distinguished element. |
| 82 |
|
|
The function patch_css search for the textual representation of this |
| 83 |
|
|
element and replace it with the PHP code. **) |
| 84 |
abate |
341 |
|
| 85 |
|
|
let php_css : String = |
| 86 |
|
|
[' <?php |
| 87 |
|
|
$browser = getenv("HTTP_USER_AGENT"); |
| 88 |
|
|
if (preg_match("/MSIE/i", "$browser")) { |
| 89 |
|
|
$css = "<link rel=\\"stylesheet\\" href=\\"cduce.css\\" |
| 90 |
|
|
type=\\"text/css\\">"; |
| 91 |
|
|
} elseif (preg_match("/Mozilla/i", "$browser")) { |
| 92 |
|
|
$css = "<blink>For better presentation use a more recent version |
| 93 |
|
|
of your browser, like Netscape 6</blink>"; |
| 94 |
|
|
} if (preg_match("/Mozilla\\/5.0/i", "$browser")) { |
| 95 |
|
|
$css = "<link rel=\\"stylesheet\\" href=\\"cduce.css\\" |
| 96 |
|
|
type=\\"text/css\\">"; |
| 97 |
|
|
} elseif (preg_match("/opera/i", "$browser")) { |
| 98 |
|
|
$css = "<link rel=\\"stylesheet\\" href=\\"cduce.css\\" |
| 99 |
|
|
type=\\"text/css\\">"; |
| 100 |
|
|
} |
| 101 |
|
|
echo "$css"; |
| 102 |
|
|
?> '];; |
| 103 |
|
|
|
| 104 |
|
|
|
| 105 |
|
|
let fun patch_css (String -> String) |
| 106 |
|
|
| [ a::_*? '<meta content="css"/>'; rem ] -> a @ php_css @ rem |
| 107 |
|
|
| s -> s;; |
| 108 |
|
|
|
| 109 |
|
|
|
| 110 |
|
|
|
| 111 |
abate |
343 |
(** Internal types **) |
| 112 |
abate |
341 |
|
| 113 |
|
|
type Path = [ { url = String; title = String }* ];; |
| 114 |
|
|
type Tree = { name = String; url = String; title = String; |
| 115 |
|
|
children = [Tree*] } ;; |
| 116 |
abate |
250 |
|
| 117 |
abate |
346 |
let fun url_of_name (String -> String) |
| 118 |
|
|
"index" -> "/" |
| 119 |
|
|
| s -> s @ ".html";; |
| 120 |
|
|
|
| 121 |
abate |
250 |
let fun authors ([Author+] -> String) |
| 122 |
|
|
| [ <author>a ] -> a |
| 123 |
|
|
| [ <author>a1 <author>a2 ] -> a1 @ ", and " @ a2 |
| 124 |
|
|
| [ <author>a; rem ] -> a @ ", " @ authors rem;; |
| 125 |
|
|
|
| 126 |
abate |
347 |
let fun find_local_link (sitemap : [Tree*], l : String) : Tree = |
| 127 |
abate |
341 |
match sitemap with |
| 128 |
|
|
| (h,t) -> |
| 129 |
abate |
347 |
if (h . name = l) then h |
| 130 |
abate |
341 |
else |
| 131 |
|
|
(try find_local_link (t,l) with `Not_found -> |
| 132 |
|
|
find_local_link (h . children,l)) |
| 133 |
|
|
| [] -> raise `Not_found;; |
| 134 |
|
|
|
| 135 |
abate |
347 |
let fun local_link (sitemap : Tree, l : String, txt : String) : Inline = |
| 136 |
|
|
try |
| 137 |
|
|
let h = find_local_link ([sitemap],l) in |
| 138 |
|
|
let txt = if txt = "" then h . title else txt in |
| 139 |
|
|
<a href=(h . url)>txt |
| 140 |
abate |
341 |
with `Not_found -> raise [ 'Local link not found: ' !l ];; |
| 141 |
|
|
|
| 142 |
|
|
let fun compute_sitemap ((Page|External) -> Tree) |
| 143 |
|
|
<page name=name>[ <title>title (c::(Page|External) | _)* ] -> |
| 144 |
|
|
let children = map c with p -> compute_sitemap p in |
| 145 |
abate |
346 |
{ name = name; url = url_of_name name; title = title; children =children } |
| 146 |
abate |
341 |
|<external name=name; href=h; title=t>[] -> |
| 147 |
|
|
{ name = name; url = h; title = t; children = [] };; |
| 148 |
|
|
|
| 149 |
|
|
let fun display_sitemap (h : Tree) : Xli = |
| 150 |
|
|
let ch = map h . children with x -> display_sitemap x in |
| 151 |
|
|
let ch = match ch with [] -> [] | l -> [ <ul>l ] in |
| 152 |
|
|
<li>[ <a href=(h . url)>(h . title); ch ];; |
| 153 |
|
|
|
| 154 |
abate |
343 |
(* Main transformation function *) |
| 155 |
|
|
|
| 156 |
abate |
341 |
let fun gen_page (page : Page, path : Path, sitemap : Tree) : [] = |
| 157 |
|
|
match page with |
| 158 |
|
|
<page name=name>[ <title>title <banner>banner ; items ] -> |
| 159 |
|
|
|
| 160 |
|
|
let fun text (t : [InlineText*]) : Inlines = |
| 161 |
abate |
284 |
map t with |
| 162 |
abate |
341 |
| <code>x -> <b>[ <tt>(highlight x) ] |
| 163 |
abate |
347 |
| <local href=l>txt -> local_link (sitemap,l,txt) |
| 164 |
abate |
336 |
| <(tag & (`b|`i|`tt|`em))>x -> <(tag)>(text x) |
| 165 |
abate |
348 |
| <a href=url>_ & z -> let [] = print [ 'External link: ' !url '\n'] in z |
| 166 |
abate |
341 |
| z -> z |
| 167 |
|
|
in |
| 168 |
abate |
254 |
|
| 169 |
abate |
341 |
let fun content (t : Content) : Flow = |
| 170 |
abate |
250 |
transform t with |
| 171 |
abate |
284 |
| <section title=title>c -> |
| 172 |
|
|
[ <h4>title !(content c) ] |
| 173 |
abate |
250 |
| <paper (r)>[ <title>tit aut::Author* <comment>com <abstract>ab ] -> |
| 174 |
abate |
284 |
[ (match r with { file = f } -> <a href=f>tit | _ -> <b>tit) '. ' |
| 175 |
abate |
250 |
!(authors aut) '. ' |
| 176 |
abate |
254 |
!(text com) |
| 177 |
abate |
250 |
<div class="abstract">[ 'Abstract:' !(content ab) ] |
| 178 |
|
|
] |
| 179 |
|
|
| <slides file=f>[ <title>tit aut::Author* <comment>com ] -> |
| 180 |
abate |
254 |
[ <a href=f>tit '. ' !(authors aut) '. ' !(text com) ] |
| 181 |
abate |
344 |
| <sample highlight="false">s -> |
| 182 |
|
|
[ <div class="code">[ <pre>s ] ] |
| 183 |
abate |
336 |
| <sample>s -> |
| 184 |
abate |
340 |
[ <div class="code">[ <pre>(highlight s) ] ] |
| 185 |
abate |
284 |
| <link url=url; title=title>com -> |
| 186 |
|
|
[ <a href=url>title '. ' !(text com) ] |
| 187 |
|
|
| <ul>lis -> |
| 188 |
|
|
[ <ul>(map lis with <li>x -> <li>(content x)) ] |
| 189 |
|
|
| Xtable & x -> |
| 190 |
|
|
[ x ] |
| 191 |
abate |
254 |
| <p>x -> [ <p>(text x) ] |
| 192 |
abate |
341 |
| <pages-toc>[] -> |
| 193 |
|
|
let toc = |
| 194 |
|
|
transform items with |
| 195 |
abate |
346 |
| <page name=l>[<title>t;_] -> [ <li>[ <a href=(url_of_name l)>t ] ] |
| 196 |
abate |
341 |
| <external href=l; title=t>[] -> [ <li>[ <a href=l>t ] ] in |
| 197 |
|
|
(match toc with [] -> [] | lis -> [ <ul>lis ]) |
| 198 |
|
|
| <boxes-toc>[] -> |
| 199 |
|
|
let toc = |
| 200 |
|
|
transform items with |
| 201 |
|
|
<box title=t; link=l>_ -> [ <li>[ <a href=('#',l)>t ] ] in |
| 202 |
|
|
(match toc with [] -> [] | lis -> [ <ul>lis ]) |
| 203 |
|
|
| <site-toc>[] -> |
| 204 |
|
|
[ <ul>[ (display_sitemap sitemap) ] ] |
| 205 |
|
|
| <local-links href=s>[] -> |
| 206 |
|
|
(match (split_comma s) with |
| 207 |
|
|
| [] -> [] |
| 208 |
abate |
347 |
| l -> let l = map l with x -> <li>[ (local_link(sitemap,x,"")) ] |
| 209 |
abate |
341 |
in [ <ul>l ]) |
| 210 |
|
|
| t -> text [ t ] |
| 211 |
|
|
in |
| 212 |
abate |
250 |
|
| 213 |
abate |
341 |
let main : Flow = transform items with |
| 214 |
|
|
| <box (r)>c -> |
| 215 |
|
|
[ <div class="box">[ |
| 216 |
|
|
<h2>(r . title) |
| 217 |
|
|
!(match r with { subtitle = t } -> [<b>t] | _ -> []) |
| 218 |
|
|
<a name=r . link>[] |
| 219 |
|
|
!(content c) ] ] |
| 220 |
|
|
| <meta>c -> [ <div class="meta">(content c) ] |
| 221 |
abate |
250 |
in |
| 222 |
abate |
341 |
let navig : Flow = transform items with |
| 223 |
|
|
| <left>c -> [<div class="box">(content c)] |
| 224 |
|
|
in |
| 225 |
|
|
let dpath : Inlines = transform path with |
| 226 |
|
|
| { url = f; title = t } -> [ <a href=f>t ' :: '] |
| 227 |
|
|
in |
| 228 |
|
|
let html : Xhtml = |
| 229 |
abate |
250 |
<html>[ |
| 230 |
|
|
<head>[ |
| 231 |
|
|
<title>title |
| 232 |
|
|
<meta content="text/html; charset=iso-8859-1"; http-equiv="Content-Type">[] |
| 233 |
abate |
284 |
<meta content="css">[] (* Placeholder for PHP code *) |
| 234 |
abate |
250 |
] |
| 235 |
|
|
<body>[ |
| 236 |
abate |
341 |
<div class="title">[ <h1>(text banner) <p>[ !dpath !title ] ] |
| 237 |
abate |
250 |
<div id="Sidelog">navig |
| 238 |
abate |
341 |
<div id="Content">main |
| 239 |
abate |
250 |
] |
| 240 |
abate |
341 |
] |
| 241 |
|
|
in |
| 242 |
|
|
let txt : String = |
| 243 |
|
|
[ (* '<?xml version="1.0" encoding="iso-8859-1"?>' *) |
| 244 |
|
|
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' |
| 245 |
|
|
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' |
| 246 |
|
|
!(patch_css (print_xml html)) ] in |
| 247 |
abate |
346 |
let [] = dump_to_file (name @ ".html.php") txt in |
| 248 |
|
|
let url = url_of_name name in |
| 249 |
|
|
let path = path @ [ { url = url; title = title } ] in |
| 250 |
abate |
341 |
transform items with p & Page -> gen_page (p,path,sitemap);; |
| 251 |
|
|
|
| 252 |
abate |
250 |
|
| 253 |
abate |
343 |
(* Entry point *) |
| 254 |
abate |
284 |
|
| 255 |
abate |
341 |
match load_include "site.xml" with |
| 256 |
abate |
343 |
| [ Page & p ] -> gen_page (p,[], compute_sitemap p) |
| 257 |
abate |
341 |
| _ -> raise "Invalid site.xml";; |
| 258 |
abate |
255 |
|