site.cd 7.97 KB
Newer Older
1
2
(* This CDuce script produces CDuce web site. *)

3
(** Output types **)
4

5
6
include "xhtml-strict.cd";;  (* XHTML 1 Strict DTD *)
include "xhtml-categ.cd";;   (* Categories (Inline, ...) from this DTD *)
7

8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(** Input types **)

type Page =  <page name=String>[ <title>String <banner>[InlineText*] Item* ];;
type External = <external {|href=String; title=String; name=String |}>[];;

type Item = 
   <box title=String; subtitle=?String; link=String>Content
 | <meta>Content
 | <left>Content
 | Page
 | External;;

type Author = <author>String;;
type Paper = 
  <paper file=?String>[ 
     <title>String Author+ <comment>[InlineText*] <abstract>Content ];;

type Slides = 
  <slides file=String>[ <title>String Author+ <comment>[InlineText*] ];;

type Link =
  <link url=String; title=String>[ InlineText* ];;

type Content =      
   [ ( <p {||}>[InlineText*]
     | <ul {||}>[<li {||}>Content +]
     | <section title=String>Content
36
     | <sample highlight=?"true"|"false">String
37
38
39
40
41
42
43
44
45
46
47
48
49
     | Xtable
     | Paper | Slides | Link
     | <boxes-toc>[]
     | <pages-toc>[]
     | <site-toc>[]
     | <local-links href=String>[]
     | InlineText
     )* ];;

type InlineText =
     Char
   | <(`b|`i|`tt|`em) {||}>[InlineText*]
   | <code>String
50
   | <local href=String>String
51
52
53
54
55
56
57
   | Xa | Ximg | Xbr ;;


(** Generic purpose functions **)

(* Recursive inclusion of XML files and verbatim text files *)

58
59
60
61
let fun load_include (String -> [Any*])
 name ->
   let _ = print [ 'Loading ' !name '... \n' ] in
   xtransform [ (load_xml name) ] with 
62
63
   | <include file=(s & String)>[] -> load_include s
   | <include-verbatim file=(s & String)>[] -> load_file s;; 
64

65
(* Highlighting text between {{...}} *)
66

67
68
69
70
let fun highlight (String -> [ (Char | Xvar)* ] )
 | [ '{{' h ::(Char *?) '}}' ; rest ] -> 
          [ <var class="highlight">h; highlight rest ]
 | [ c; rest ] -> [ c; highlight rest ]
71
72
 | [] -> [];;

73
74
(* Split a comma-separated string *)

75
76
77
78
79
let fun split_comma (String -> [String*])
 | [ x::(Char*?) ',' ; rest ] -> (x, split_comma rest)
 | s -> [ s ];;


80
81
82
83
(** Ugly hack to introduce PHP code ...
    The idea is to produce first an XML document with a distinguished element.
    The function patch_css search for the textual representation of this
    element and replace it with the PHP code. **)
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

let php_css : String =
[' <?php
$browser = getenv("HTTP_USER_AGENT");
if (preg_match("/MSIE/i", "$browser")) {
        $css = "<link rel=\\"stylesheet\\" href=\\"cduce.css\\"
type=\\"text/css\\">";
} elseif (preg_match("/Mozilla/i", "$browser")) {
        $css = "<blink>For better presentation use a more recent version
of your browser, like Netscape 6</blink>";
} if (preg_match("/Mozilla\\/5.0/i", "$browser")) {
        $css = "<link rel=\\"stylesheet\\" href=\\"cduce.css\\"
type=\\"text/css\\">";
} elseif  (preg_match("/opera/i", "$browser")) {
        $css = "<link rel=\\"stylesheet\\" href=\\"cduce.css\\"
type=\\"text/css\\">";
}
echo "$css";
?> '];;


let fun patch_css (String -> String)
| [ a::_*? '<meta content="css"/>'; rem ] -> a @ php_css @ rem
| s -> s;;



111
(** Internal types **)
112

113
114
115
type Path = [ { url = String; title = String }* ];;
type Tree = { name = String; url = String; title = String; 
              children = [Tree*] } ;;
116

117
118
119
120
let fun url_of_name (String -> String)
   "index" -> "/"
 | s -> s @ ".html";;

121
122
123
124
125
let fun authors ([Author+] -> String)
   | [ <author>a ] -> a
   | [ <author>a1 <author>a2 ] -> a1 @ ", and " @ a2
   | [ <author>a; rem ] -> a @ ", " @ authors rem;;

126
let fun find_local_link (sitemap : [Tree*], l : String) : Tree =
127
128
match sitemap with
 | (h,t) ->
129
   if (h . name = l) then h
130
131
132
133
134
   else 
    (try find_local_link (t,l) with `Not_found -> 
         find_local_link (h . children,l))
 | [] -> raise `Not_found;;

135
136
137
138
139
let fun local_link (sitemap : Tree, l : String, txt : String) : Inline =
 try 
  let h = find_local_link ([sitemap],l)  in
  let txt = if txt = "" then h . title else txt in
  <a href=(h . url)>txt
140
141
142
143
144
 with `Not_found -> raise [ 'Local link not found: ' !l ];;
 
let fun compute_sitemap ((Page|External) -> Tree)
 <page name=name>[ <title>title (c::(Page|External) | _)* ] ->
   let children = map c with p -> compute_sitemap p in
145
   { name = name; url = url_of_name name; title = title; children =children }
146
147
148
149
150
151
152
153
|<external name=name; href=h; title=t>[] ->
   { name = name; url = h; title = t; children = [] };;

let fun display_sitemap (h : Tree) :  Xli =
  let ch = map h . children with x -> display_sitemap x in
  let ch = match ch with [] -> [] | l -> [ <ul>l ] in
  <li>[ <a href=(h . url)>(h . title); ch ];;

154
155
(* Main transformation function *)

156
157
158
159
160
let fun gen_page (page : Page, path : Path, sitemap : Tree) : [] = 
match page with
<page name=name>[ <title>title <banner>banner ; items ] ->

 let fun text (t : [InlineText*]) : Inlines =
161
  map t with
162
   | <code>x -> <b>[ <tt>(highlight x) ]
163
   | <local href=l>txt -> local_link (sitemap,l,txt)
164
   | <(tag & (`b|`i|`tt|`em))>x -> <(tag)>(text x)
165
   | <a href=url>_ & z -> let [] = print [ 'External link: ' !url '\n'] in z
166
167
   | z -> z
 in
168

169
 let fun content (t : Content) : Flow =
170
  transform t with
171
172
   | <section title=title>c -> 
         [ <h4>title !(content c) ]
173
   | <paper (r)>[ <title>tit aut::Author* <comment>com <abstract>ab  ]  ->
174
         [ (match r with { file = f } -> <a href=f>tit | _ -> <b>tit) '. '
175
           !(authors aut) '. '
176
	   !(text com)
177
178
179
           <div class="abstract">[ 'Abstract:' !(content ab) ]
         ]
   | <slides file=f>[ <title>tit aut::Author* <comment>com ]  ->
180
        [ <a href=f>tit '. ' !(authors aut) '. ' !(text com) ]
181
182
   | <sample highlight="false">s ->
        [ <div class="code">[ <pre>s ] ]
183
   | <sample>s ->
184
        [ <div class="code">[ <pre>(highlight s) ] ]
185
186
187
188
189
190
   | <link url=url; title=title>com -> 
        [ <a href=url>title '. ' !(text com) ]
   | <ul>lis -> 
        [ <ul>(map lis with <li>x -> <li>(content x)) ]
   | Xtable & x -> 
        [ x ]
191
   | <p>x -> [ <p>(text x) ]
192
193
194
   | <pages-toc>[] ->
        let toc = 
         transform items with 
195
         | <page name=l>[<title>t;_] ->  [ <li>[ <a href=(url_of_name l)>t ] ]
196
197
198
199
200
201
202
203
204
205
206
207
         | <external href=l; title=t>[] -> [ <li>[ <a href=l>t ] ] in
        (match toc with [] -> [] | lis -> [ <ul>lis ])
   | <boxes-toc>[] ->
        let toc = 
         transform items with 
          <box title=t; link=l>_ -> [ <li>[ <a href=('#',l)>t ] ] in
        (match toc with [] -> [] | lis -> [ <ul>lis ])
   | <site-toc>[] ->
        [ <ul>[ (display_sitemap sitemap) ] ]
   | <local-links href=s>[] ->
         (match (split_comma s) with
           | [] -> []
208
           | l -> let l = map l with x -> <li>[ (local_link(sitemap,x,"")) ]
209
210
211
                  in [ <ul>l ])
   | t -> text [ t ]
 in
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
 let main : Flow = transform items with
  | <box (r)>c ->
     [ <div class="box">[
         <h2>(r . title)
          !(match r with { subtitle = t } -> [<b>t] | _ -> [])
         <a name=r . link>[] 
         !(content c)  ] ]
  | <meta>c -> [ <div class="meta">(content c) ] 
 in
 let navig : Flow = transform items with 
  | <left>c -> [<div class="box">(content c)] 
 in
 let dpath : Inlines = transform path with 
  | { url = f; title = t } -> [ <a href=f>t ' :: '] 
227
 in
228
 let html : Xhtml =
229
230
 <html>[
  <head>[ 
231
   <title>[ 'CDuce: ' !title ]
232
   <meta content="text/html; charset=iso-8859-1"; http-equiv="Content-Type">[]
233
   <meta content="css">[]  (* Placeholder for PHP code *)
234
235
  ]
  <body>[ 
236
237
   <div class="title">[ <h1>(text banner) 
                        <p>[ <b>"You're here: " !dpath !title ] ]
238
   <div id="Sidelog">navig
239
   <div id="Content">main
240
  ]
241
242
243
244
245
246
247
 ]
 in
 let txt : String = 
   [ (* '<?xml version="1.0" encoding="iso-8859-1"?>' *)
     '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'
     '  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
     !(patch_css (print_xml html)) ] in
248
249
250
 let [] = dump_to_file (name @ ".html.php") txt in
 let url = url_of_name name in
 let path = path @ [ { url = url; title = title } ] in
251
252
253
 transform items with p & Page -> gen_page (p,path,sitemap);;
    

254
(* Entry point *)
255
256

match load_include "site.xml" with
257
 | [ Page & p ] -> gen_page (p,[], compute_sitemap p)
258
 | _ -> raise "Invalid site.xml";;
259