(* This CDuce script produces CDuce web site. *) include "xhtml-strict.cd";; (* XHTML 1 Strict DTD *) include "xhtml-categ.cd";; (* Categories (Inline, ...) from this DTD *) let fun load_include (String -> [Any*]) name -> let _ = print [ 'Loading ' !name '... \n' ] in xtransform [ (load_xml name) ] with [] -> load_include s;; let fun hilight (String -> [ (Char | Xvar)* ] ) | [ '{{' h ::(Char *?) '}}' ; rest ] -> [ h; hilight rest ] | [ c; rest ] -> [ c; hilight rest ] | [] -> [];; type SitePage = Page | [];; type Site = [ SitePage* ];; type Page = [ String <banner>[InlineText*] <navig>[ NavigBox* ] <main>[ Box* ] ];; 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 | <sample>String | Xtable | Paper | Slides | Link | <include-verbatim file=String>[] | InlineText )* ];; type InlineText = Char | <(`b|`i|`tt|`em) {||}>[InlineText*] | <duce>String | Xa | Ximg | Xbr ;; type Box = <box title=String; subtitle=?String; link=String>Content | <meta>Content;; type NavigBox = <box>Content | <toc>[];; let fun authors ([Author+] -> String) | [ <author>a ] -> a | [ <author>a1 <author>a2 ] -> a1 @ ", and " @ a2 | [ <author>a; rem ] -> a @ ", " @ authors rem;; let fun text (t : [InlineText*]) : Inlines = map t with | <duce>x -> <b>[ <tt>(hilight x) ] | <(tag & (`b|`i|`tt|`em))>x -> <(tag)>(text x) | z -> z;; let fun content (t : Content) : Flow = transform t with | <section title=title>c -> [ <h4>title !(content c) ] | <paper (r)>[ <title>tit aut::Author* <comment>com <abstract>ab ] -> [ (match r with { file = f } -> <a href=f>tit | _ -> <b>tit) '. ' !(authors aut) '. ' !(text com) <div class="abstract">[ 'Abstract:' !(content ab) ] ] | <slides file=f>[ <title>tit aut::Author* <comment>com ] -> [ <a href=f>tit '. ' !(authors aut) '. ' !(text com) ] | <include-verbatim file=f>[] -> [ <div class="code">[ <pre>(load_file f) ] ] | <sample>s -> [ <div class="code">[ <pre>(hilight s) ] ] | <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 ] | <p>x -> [ <p>(text x) ] | x -> text [ x ];; let fun main2html (Box -> Flow) <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) ];; (* 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. *) 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;; let fun page2html (Page -> Xhtml) <page>[ <title>title <banner>banner <navig>navig <main>main ] -> let toc = transform main with <box title=t; link=l>_ -> [ <li>[ <a href=('#',l)>t ] ] in let toc = match toc with [] -> [] | lis -> [ <ul>lis ] in let navig : Flow = transform navig with | <box>c -> [ <div class="box">(content c) ] | <toc>[] -> [ <div class="box">toc ] in <html>[ <head>[ <title>title <meta content="text/html; charset=iso-8859-1"; http-equiv="Content-Type">[] <meta content="css">[] (* Placeholder for PHP code *) ] <body>[ <div class="title">[ <h1>(text banner) ] <div id="Sidelog">navig <div id="Content">(transform main with b -> main2html b) ] ];; type P = (String,<title>String);; let fun make_plan (l : [ P+ ]) : Page = <page output="plan.php">[ <title>"CDuce site" <banner>"CDuce site" <navig>[ <box>[ <a href="/">"Home" ] ] <main>[ <box title="Pages"; link="pages">[ <ul>(map l with (file,<title>t) -> <li>[<a href=file>t]) ] <meta>[ 'This page was automatically generated by a CDuce program.' ] ] ];; let fun do_page(Page -> P) <page output=outf>[ tit & <title>_; _ ] & page -> let _ = print [ 'Generating html... ' ] in let html : 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 (page2html page))) ] in let _ = print [ 'Saving to ' !outf '...\n' ] in let _ = dump_to_file outf html in (outf, tit);; let site = match load_include "site.xml" with | [ Site & <site>s ] -> let ts = map s with | Page & p -> do_page p | <external href=url; title=t>_ -> (url,<title>t) in let _ = print [ 'Create plan... ' ] in let plan = make_plan (ts @ [("plan.php", <title>"CDuce site")]) in let _ = do_page plan in [] | _ -> raise "Invalid site.xml";;