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

3
4
5
6
7
8
(** Command line **)

let (input, php) =
  match argv with
  | [ "-php" s ] -> (s, `true)
  | [ s ] -> (s, `false)
9
  | _ -> raise "Please specify an input file on the command line"
10
11


12
(** Output types **)
13

14
15
include "xhtml-strict.cd"  (* XHTML 1 Strict DTD *)
include "xhtml-categ.cd"   (* Categories (Inline, ...) from this DTD *)
16

17

18
19
(** Input types **)

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

type Item = 
24
   <box title=String subtitle=?String link=String>Content
25
26
27
 | <meta>Content
 | <left>Content
 | Page
28
 | External
29

30
type Author = <author>String
31
32
type Paper = 
  <paper file=?String>[ 
33
     <title>String Author+ <comment>[InlineText*] <abstract>Content ]
34
35

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

type Link =
39
  <link url=String title=String>[ InlineText* ]
40
41
42
43
44

type Content =      
   [ ( <p {||}>[InlineText*]
     | <ul {||}>[<li {||}>Content +]
     | <section title=String>Content
45
     | <sample highlight=?"true"|"false">String
46
47
48
49
50
51
     | Xtable
     | Paper | Slides | Link
     | <boxes-toc>[]
     | <pages-toc>[]
     | <site-toc>[]
     | <local-links href=String>[]
52
     | <two-columns>[ <left>Content <right>Content ]
53
     | InlineText
54
     )* ]
55
56
57
58
59

type InlineText =
     Char
   | <(`b|`i|`tt|`em) {||}>[InlineText*]
   | <code>String
60
   | <local href=String>String
61
   | Xa | Ximg | Xbr 
62
63
64
65
66
67


(** Generic purpose functions **)

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

68
let load_include (String -> [Any*])
69
 name ->
70
(*   let _ = print [ 'Loading ' !name '... \n' ] in *)
71
   xtransform [ (load_xml name) ] with 
72
   | <include file=(s & String)>[] -> load_include s
73
   | <include-verbatim file=(s & String)>[] -> load_file s 
74

75
(* Highlighting text between {{...}} *)
76

77
let highlight (String -> [ (Char | Xvar | Xi)* ] )
78
79
 | [ '{{' h ::(Char *?) '}}' ; rest ] -> 
          [ <var class="highlight">h; highlight rest ]
80
 | [ '%%' h ::(Char *?) '%%' ; rest ] ->
81
          [ <i>h; highlight rest ]
82
 | [ c; rest ] -> [ c; highlight rest ]
83
 | [] -> []
84

85
86
(* Split a comma-separated string *)

87
let split_comma (String -> [String*])
88
 | [ x::(Char*?) ',' ; rest ] -> (x, split_comma rest)
89
 | s -> [ s ]
90
91


92
93
94
95
(** 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. **)
96

97
let css : Latin1 = 
98
  ['<link rel="stylesheet" href="cduce.css" type="text/css">']
99

100
101
let protect_quote (s : Latin1) : Latin1 =
  transform s with '"' -> [ '\\"' ] | c -> [c]
102

103
let php_css : Latin1 =
104
if php then
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
[' <?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";
121
?> ']
122
else css
123
124

(** It does not work with IE
125
126
127
128
129
130
if php then
[' <?php $browser = getenv("HTTP_USER_AGENT");
if (preg_match("/Mozilla/i", "$browser") && !preg_match("/Mozilla\\/5.0/i", "$browser")) 
{ 
  echo "<blink>For better presentation use a more recent version of
your browser, like Netscape 6</blink>"; 
131
}
132
133
else { echo "' !(protect_quote css) '"; }
?> ']
134
else css
135
**)
136

137
let patch_css (Latin1 -> Latin1)
138
| [ a::_*? '<meta content="css"/>'; rem ] -> a @ php_css @ rem
139
| s -> s
140
141
142



143
(** Internal types **)
144

145
type Path = [ { url = String; title = String }* ]
146
type Tree = { name = String; url = String; title = String; 
147
              children = [Tree*] } 
148

149
let url_of_name (String -> String)
150
   "index" -> "/"
151
 | s -> s @ ".html"
152

153
let authors ([Author+] -> String)
154
155
   | [ <author>a ] -> a
   | [ <author>a1 <author>a2 ] -> a1 @ ", and " @ a2
156
   | [ <author>a; rem ] -> a @ ", " @ authors rem
157

158
let find_local_link (sitemap : [Tree*], l : String) : Tree =
159
160
match sitemap with
 | (h,t) ->
161
   if (h . name = l) then h
162
163
164
   else 
    (try find_local_link (t,l) with `Not_found -> 
         find_local_link (h . children,l))
165
 | [] -> raise `Not_found
166

167
let local_link (sitemap : Tree, l : String, txt : String) : Inline =
168
169
170
171
 try 
  let h = find_local_link ([sitemap],l)  in
  let txt = if txt = "" then h . title else txt in
  <a href=(h . url)>txt
172
 with `Not_found -> raise [ 'Local link not found: ' !l ]
173
 
174
let compute_sitemap ((Page|External) -> Tree)
175
176
 <page name=name>[ <title>title (c::(Page|External) | _)* ] ->
   let children = map c with p -> compute_sitemap p in
177
   { name = name; url = url_of_name name; title = title; children =children }
178
|<external name=name href=h title=t>[] ->
179
   { name = name; url = h; title = t; children = [] }
180

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

186
187
let link_to (Page -> Xa)
 <page name=n>[<title>t ; _ ] -> <a href=(url_of_name n)>t
188

189
190
(* Main transformation function *)

191
(* returns the last page of the descendance *)
192
let gen_page (prev : Page|[], page : Page, next : Page|[], 
193
                  path : Path, sitemap : Tree) : (Page|[]) = 
194
match page with
195
196
<page name=name>[ 
        <title>title <banner>banner | <title>(title & banner); items ] ->
197

198
 let text (t : [InlineText*]) : Inlines =
199
  map t with
200
   | <code>x -> <b>[ <tt>(highlight x) ]
201
   | <local href=l>txt -> local_link (sitemap,l,txt)
202
   | <(tag & (`b|`i|`tt|`em))>x -> <(tag)>(text x)
203
(*   | <a href=url>_ & z -> let [] = print [ 'Link: ' !url '\n'] in z *)
204
205
   | z -> z
 in
206

207
 let content (t : Content) : Flow =
208
  transform t with
209
210
   | <section title=title>c -> 
         [ <h4>title !(content c) ]
211
   | <paper (r)>[ <title>tit aut::Author* <comment>com <abstract>ab  ]  ->
212
         [ (match r with { file = f } -> <a href=f>tit | _ -> <b>tit) '. '
213
           !(authors aut) '. '
214
	   !(text com)
215
216
217
           <div class="abstract">[ 'Abstract:' !(content ab) ]
         ]
   | <slides file=f>[ <title>tit aut::Author* <comment>com ]  ->
218
        [ <a href=f>tit '. ' !(authors aut) '. ' !(text com) ]
219
220
   | <sample highlight="false">s ->
        [ <div class="code">[ <pre>s ] ]
221
   | <sample>s ->
222
        [ <div class="code">[ <pre>(highlight s) ] ]
223
   | <link url=url title=title>com -> 
224
225
226
227
228
        [ <a href=url>title '. ' !(text com) ]
   | <ul>lis -> 
        [ <ul>(map lis with <li>x -> <li>(content x)) ]
   | Xtable & x -> 
        [ x ]
229
   | <p>x -> [ <p>(text x) ]
230
231
232
   | <pages-toc>[] ->
        let toc = 
         transform items with 
233
         | Page & p ->  [ <li>[ (link_to p) ] ]
234
         | <external href=l title=t>[] -> [ <li>[ <a href=l>t ] ] in
235
236
237
238
        (match toc with [] -> [] | lis -> [ <ul>lis ])
   | <boxes-toc>[] ->
        let toc = 
         transform items with 
239
          <box title=t link=l>_ -> [ <li>[ <a href=('#',l)>t ] ] in
240
241
242
243
244
245
        (match toc with [] -> [] | lis -> [ <ul>lis ])
   | <site-toc>[] ->
        [ <ul>[ (display_sitemap sitemap) ] ]
   | <local-links href=s>[] ->
         (match (split_comma s) with
           | [] -> []
246
           | l -> let l = map l with x -> <li>[ (local_link(sitemap,x,"")) ]
247
                  in [ <ul>l ])
248
249
250
251
252
   | <two-columns>[ <left>x <right>y ] ->
	[ <table width="100%">[ 
            <tr>[ 
              <td valign="top">(content x) 
              <td valign="top">(content y) ] ] ]
253
254
   | t -> text [ t ]
 in
255

256
257
258
259
260
 let main : Flow = transform items with
  | <box (r)>c ->
     [ <div class="box">[
         <h2>(r . title)
          !(match r with { subtitle = t } -> [<b>t] | _ -> [])
261
         <a name=(r . link)>[] 
262
263
264
265
266
267
         !(content c)  ] ]
  | <meta>c -> [ <div class="meta">(content c) ] 
 in
 let navig : Flow = transform items with 
  | <left>c -> [<div class="box">(content c)] 
 in
268
 let left = match navig with
269
270
  | [] -> [<div class="box">(content [<boxes-toc>[]])]
  | n -> n in
271
 let dpath : Inlines = transform path with 
272
  | { url = f; title = t } -> [ <a href=f>t ': '] 
273
 in
274
275
 let npath = path @ [ { url = url_of_name name; title = title } ] in
 let subpages = transform items with p & Page -> [ p ] in
276
 let (next,last) = gen_page_seq (page, subpages, next, npath, sitemap) in
277
278
279
 let next = match next with [] -> [] 
   | <page name=n>[ <title>t; _ ] -> 
      [ <a href=(url_of_name n)>[ 
280
          <img width="16" height="16" class="icon" alt="Next page" src="img/right.gif">[]
281
282
283
284
285
          ' ' !t
        ] ] in
 let prev = match prev with [] -> [] 
   | <page name=n>[ <title>t; _ ] -> 
      [ <a href=(url_of_name n)>[ 
286
          <img width="16" height="16" class="icon" alt="Previous page" src="img/left.gif">[]
287
288
289
290
291
292
293
          ' ' !t
        ] ] in
 let navig : [ Xdiv* ] = 
   if prev = [] then [] else
   [ <div class="box">[
     <p>[ !dpath !title ]
     <p>[ !prev ' ' !next ] ] ] in
294
 let html : Xhtml =
295
296
 <html>[
  <head>[ 
297
   <title>[ 'CDuce: ' !title ]
298
   <meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">[]
299
   <meta content="css">[]  (* Placeholder for PHP code *)
300
301
  ]
  <body>[ 
302
303
304
   <div class="title">[ <h1>(text banner) ]
   <div id="Sidelog">left
   <div id="Content">( navig @ main @ navig )
305
  ]
306
307
 ]
 in
308
 let txt : Latin1 = 
309
   [ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'
310
311
     '  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
     !(patch_css (print_xml html)) ] in
312
313
 let fn = "www/" @ name @ (if php then ".html.php" else ".html") in
 let [] = dump_to_file fn txt in
314
 last
315
	
316

317
let gen_page_seq 
318
 (prev : Page|[], pages : [Page*], next : Page|[], 
319
  path : Path, sitemap : Tree) : (Page|[], Page|[]) =
320
321
 match pages with
 | [ p1 p2 ; _ ] & [ _; rest ] -> 
322
323
324
     let last = gen_page (prev,p1,p2, path, sitemap) in
     let (_,last)  = gen_page_seq (last, rest, next, path, sitemap) in 
     (p1,last)
325
 | [ p ] ->
326
     let last = gen_page (prev,p,next, path, sitemap) in (p,last)
327
 | [] -> (next,prev)
328

329

330
;;
331

332
match load_include input with
333
 | [ Page & p ] -> let _ = gen_page ([],p,[], [], compute_sitemap p) in []
334
 | _ -> raise ("Invalid input document " @ input)
335