Changeset main,5
- Timestamp:
- 06/09/2008 09:54:47 PM (18 years ago)
- branch-nick:
- tags
- revision id:
- dsowen@fugue88.ws-20080609215447-gufu5u9zswt1bhng
- Location:
- main
- Files:
-
- 2 edited
-
dso-tags.asd (modified) (2 diffs)
-
tags.lisp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
main/dso-tags.asd
r4 r5 2 2 3 3 #| 4 Copyright (C) 2008 David Owen 4 Copyright (C) 2008 David Owen <dsowen@fugue88.ws> 5 5 6 6 This program is free software: you can redistribute it and/or modify … … 19 19 20 20 (asdf:defsystem #:dso-tags 21 :depends-on (#:cl-ppcre )21 :depends-on (#:cl-ppcre #:dso-util) 22 22 :components ((:file "tags"))) -
main/tags.lisp
r4 r5 1 1 #| 2 Copyright (C) 2008 David Owen 2 Copyright (C) 2008 David Owen <dsowen@fugue88.ws> 3 3 4 4 This program is free software: you can redistribute it and/or modify … … 17 17 18 18 (defpackage #:dso-tags 19 (:use #:cl #:cl-ppcre )20 (:export #:*tag-out* #: expand-tag #:render-tag #:do-body))19 (:use #:cl #:cl-ppcre #:dso-util) 20 (:export #:*tag-out* #:deftag #:expand-tag #:render-tag #:do-body #:xhtml)) 21 21 22 22 (in-package #:dso-tags) 23 24 25 26 (let ((tbl '(("<" . "<") 27 (">" . ">") 28 ("&" . "&") 29 ("'" . "'") 30 ("\"" . """)))) 31 (defun xml-entity (str) 32 (let ((pair (assoc str tbl :test 'string=))) 33 (assert pair (str) "The string ~S is not an XML entity." str) 34 (cdr pair)))) 35 36 (flet ((f (str d1 d2 start end &rest dummy) 37 (declare (ignore d1 d2 dummy)) 38 (xml-entity (subseq str start end)))) 39 (defun xml-escape (set str) 40 (cl-ppcre:regex-replace-all set str #'f))) 41 42 (defun xml-escape-pcdata (str) 43 (xml-escape "[<>&]" str)) 44 45 (defun xml-escape-attr (str) 46 (xml-escape "['\"]" str)) 23 47 24 48 … … 29 53 30 54 (defgeneric expand-tag (tag body &key &allow-other-keys) 55 (:documentation 56 "Specialize this to create your own tags.") 31 57 (:method (tag body &key))) 32 58 … … 51 77 (etypecase item 52 78 (string 53 (format *tag-out* "~A" (regex-replace-all "([^ ]) ([^ ])" item "\\1 \\2"))) 79 (format *tag-out* "~A" 80 (regex-replace-all "([^ ]) ([^ ])" 81 (xml-escape-pcdata item) 82 "\\1 \\2"))) 54 83 (list 55 84 (multiple-value-bind (tag-name tag-body tag-attrs) (break-tag item) 56 85 (let ((expanded (apply 'expand-tag tag-name tag-body tag-attrs))) 57 86 (if expanded 58 (setf body ( nconcexpanded body))87 (setf body (append expanded body)) 59 88 (apply 'render-tag tag-name tag-body tag-attrs)))))))) 60 89 … … 63 92 (defun render-empty-tag (tag body args) 64 93 (assert (null body)) 65 (format *tag-out* "<~(~A~)~{ ~(~A~)='~A'~}/>" tag args)) 94 (format *tag-out* "<~(~A~)~{ ~(~A~)='~A'~} />" 95 tag 96 (loop for (key value) on args by #'cddr 97 append (list key (xml-escape-attr value))))) 66 98 67 99 (defun render-simple-tag (tag body args) 68 100 (if body 69 101 (progn 70 (format *tag-out* "<~(~A~)~{ ~(~A~)='~A'~}>" tag args) 102 (format *tag-out* "<~(~A~)~{ ~(~A~)='~A'~}>" 103 tag 104 (loop for (key value) on args by #'cddr 105 append (list key (xml-escape-attr value)))) 71 106 (do-body body) 72 107 (format *tag-out* "</~(~A~)>" tag)) … … 75 110 (defmethod render-tag (tag body &rest args &key &allow-other-keys) 76 111 (render-simple-tag tag body args)) 112 113 (defmethod render-tag ((tag (eql 'xhtml)) body &key &allow-other-keys) 114 (format *tag-out* "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" 115 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">") 116 (call-next-method 'html body :xmlns "http://www.w3.org/1999/xhtml")) 117 118 119 120 (defmacro deftag% (name (body-var &rest key-vars) &body body) 121 `(defmethod expand-tag ((,(gensym) (eql ',name)) ,body-var &key ,@key-vars) 122 ,@body)) 123 124 (defmacro deftag (name (body-vars &rest key-vars) &body body) 125 (if (symbolp body-vars) 126 `(deftag% ,name (,body-vars ,@key-vars) ,@body) 127 (with-gensyms (b) 128 `(deftag% ,name (,b ,@key-vars) 129 (destructuring-bind (,@body-vars) ,b 130 ,@body)))))
Note: See TracChangeset
for help on using the changeset viewer.
