; template.ss - Simple template ; ; Copyright (c) 2011 Higepon(Taro Minowa) ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; ; 1. Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; ; 2. Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; (library (template) (export template-vars template->sexp eval-template eval-template-file ref h template-dir) (import (rnrs) (shorten) (mosh) (mosh file) (srfi :39) (rnrs eval) (rename (mosh cgi) (escape h)) (mosh control)) (define template-vars (make-parameter #f)) (define template-dir (make-parameter #f)) (define-syntax ref (lambda (x) (syntax-case x () [(_ alist key) #'(assoc-ref alist 'key)]))) (define (eval-template-file file vars . import-spec*) (let1 path (if (template-dir) (string-append (template-dir) "/" file) file) (apply eval-template (file->string path) vars import-spec*))) (define (eval-template template vars . import-spec*) (parameterize ([template-vars vars]) (let1 templ (template->sexp template vars) (if (eof-object? templ) '() (eval templ (apply environment '(rnrs) '(mosh) '(template) '(match) import-spec*)))))) ;; http://d.hatena.ne.jp/yuum3/20080203/1202049898 (define (compile-elem templ port) ; (format (current-error-port) "\n\n~s\n\n" templ) (cond [(or (not templ) (string=? templ "")) #t] [((string->regexp "^<%include (((?!%>)(.|\n))*) %>((.|\n)*)" 's) templ) => (^m ; (format (current-error-port) "fild=<~s>" (m 1)) (let1 path (if (template-dir) (string-append (template-dir) "/" (m 1)) (m 1)) (compile-elem (string-append (file->string path) (if (m 4) (m 4) "")) port)))] ;; comment [((string->regexp "^<%#(((?!%>)(.|\n))*)%>((.|\n)*)" 's) templ) => (^m (compile-elem (m 4) port))] [((string->regexp "^<%=unsafe(((?!%>)(.|\n))*)%>((.|\n)*)" 's) templ) => (^m (format port "(display ~a)" (m 1)) (compile-elem (m 4) port))] ;; output with escape [((string->regexp "^<%=(((?!%>)(.|\n))*)%>((.|\n)*)" 's) templ) => (^m (format port "(display (h ~a))" (m 1)) (compile-elem (m 4) port))] [((string->regexp "^<%(((?!%>)(.|\n))*)%>((.|\n)*)" 's) templ) => (^m ; (format (current-error-port) "hoge=[~s] [~s]\n" (m 1) (m 4)) (format port "~a" (m 1)) (compile-elem (m 4) port))] [((string->regexp "^(((?!<%)(.|\n))*)<%((.|\n)*)" 's) templ) => (^m ; (format (current-error-port) "hoge=[~s] [~s]\n" (m 1) (m 4)) (format port "(display ~s)" (m 1)) (compile-elem (string-append "<%" (if (m 4) (m 4) "")) port))] [else (format port "(display ~s)" templ)])) (define (template->sexp template variable*) (let-values (([port get-string] (open-string-output-port))) (compile-elem template port) (let1 body (let1 p (open-string-input-port (get-string)) (let loop ([sexp (read p)] [ret '()]) (if (eof-object? sexp) (reverse ret) (loop (read p) (cons sexp ret))))) (if (null? body) #f `(let (,@(map (^v `(,(car v) ,(cdr v))) variable*)) ,@body))))) )