#lang scheme (provide conditionalize) (provide xhtml-head) (provide xhtml-response) ; To send a response to the client, we'll need the response struct. (require web-server/http/response-structs) ; We need xml to define the pages themselves. (require xml) ; This litle function will build a conditional comment for ie browsers. Mighty usefull. ; [condition] is a string in the ie condition format, for example "if lte IE 6". ; [content] is an xexpr representing the content. ; The return value is a comment struct, that can be used in another xexpr. ; NOTE!!! This can't be rendered with xexpr->string, since it will ignore all comments. ; Use write-xml or display-xml instead. (define (conditionalize condition content) (make-comment (string-append "[" condition "]>" (xexpr->string content) "string happily ignores. ; [language] is a string with the language of the content, for examlple "en" for english or "sv" for swedish. ; [head] is an xexpr with the complete head-tag. (hint: Use xhtml-head to generate this.) ; [body] is an xexpr with the complete body-tag. (define (xhtml-response language head body) ; We need to make sure the empty tag shorthand will only be used where apropriate. (empty-tag-shorthand html-empty-tags) ; We need to return a full response struct, since an xexpr can't represent everything we need. (make-response/full 200 #"Okay" (current-seconds) TEXT/HTML-MIME-TYPE empty ; The actual page as a list of strings. (list ; The opening XML-tag. You do use UTF-8, right? RIGHT!? #"\n" ; We need a string port to write to. (let ((port (open-output-string))) ; display-xml is nice for development, since it outputs readable XHTML. ; However, the result is not always what you want. Take a look at the bunny-link ; in the example below. FF3 will link even the space after the link-tag. Ugly. ; In production, you would probably want to use the unreadable write-xml instead. ; Render the XML structure of the page to a string. (write-xml ; We'll need a document struct... (make-document ; ...which takes a "prolog"... (make-prolog empty ; ..which takes a document type (the "!DOCTYPE")... (make-document-type 'html ; ...which takes a DTD. (make-external-dtd/public "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" "-//W3C//DTD XHTML 1.0 Strict//EN") #f) empty) ; Now, the only thing missing is the actual document content. ; We'll get it by converting the document xexpr to an XML struct. (xexpr->xml ; The xexpr we get by wrapping the supplied head and body tags ; with a root HTML-tag. Oh, and we need that xmlns attribute! `(html ((xmlns "http://www.w3.org/1999/xhtml") (xml:lang "en") (lang ,language)) ,head ,body)) empty) ; We'll write to the string port we opened earlier. port) ; And return the string of the complete document. (get-output-bytes port)))))