aboutsummaryrefslogtreecommitdiffstats
path: root/who.tl
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-05-29 19:14:11 -0700
committerKaz Kylheku <kaz@kylheku.com>2023-05-29 19:14:11 -0700
commit271e541893c4d10b3b4fa8f20cb6c54f0af2527e (patch)
treed88068ca91fffbacc04359e8084b90551ea884fe /who.tl
parentff4671eca8e75611a76368eb3f3a3dde334ddb80 (diff)
downloadtl-who-271e541893c4d10b3b4fa8f20cb6c54f0af2527e.tar.gz
tl-who-271e541893c4d10b3b4fa8f20cb6c54f0af2527e.tar.bz2
tl-who-271e541893c4d10b3b4fa8f20cb6c54f0af2527e.zip
Fix CL-WHO attr bugs: no escaping, poor constant handling.
CL-WHO tries to handle the case when attribute values are constant NIL and T values, but it bungles it; it applies the correct behavior only when the constants are literally these symbols, not when they are constant expressions which evaluate to these values. Secondly, CL-WHO neglects to HTML-escape attribute values. We fix this behavior and introduce a noesc operator to selectively revert it, as well as a *cl-who-compat* special to revert the behavior more pervasively, for the daredevils. * packages.tl (tl-who): New symbols *cl-who-compat* and noesc. * specials.tl (*cl-who-compat*): New special variable. * who.tl (convert-attributes): When treating a constant expression, evaluate it first, then check for nil or t. Escape interpolated text with html-encode. Check the original expression for (noesc ...) pattern, or the presence of *cl-who-compat*. In these cases, don't generate the escape call. * test/simple.tl: New tests 28 to 37 providing some coverage to all these changes. * README.md: Document.
Diffstat (limited to 'who.tl')
-rw-r--r--who.tl49
1 files changed, 29 insertions, 20 deletions
diff --git a/who.tl b/who.tl
index 2683450..3c4a440 100644
--- a/who.tl
+++ b/who.tl
@@ -92,26 +92,35 @@
(with-gensyms (=var=)
(let ((aqc *attribute-quote-char*))
(keep-matches (^(,orig-attr . ,val) attr-list)
- (let ((attr (maybe-upcase orig-attr)))
- (if val
- (if (constantp val)
- ;; Handle constant attribute value at macro time
- (if (and *empty-attribute-syntax* (eq val t))
- ` @attr`
- ` @attr=@aqc@(if (eq val t)
- attr
- (tostringp (eval val)))@aqc`)
- ;; For non-constant, do the same things as above but at runtime
- ^(let ((,=var= ,val))
- (cond
- ((null ,=var=))
- ((eq ,=var= t)
- (str ,(if *empty-attribute-syntax*
- ^` @,attr`
- ^` @,attr=@,aqc@,attr@,aqc`)))
- (t
- (str ` @,attr=@,aqc@{,=var=}@,aqc`)))))))))))
-
+ (let ((attr (maybe-upcase orig-attr))
+ noesc)
+ (when-match (noesc . @rest) val
+ (set noesc t)
+ (set val ^(progn ,*rest)))
+ (if (constantp val)
+ ;; Handle constant attribute value at macro time
+ (let ((eval (eval val)))
+ (cond
+ ((null eval))
+ ((eq eval t)
+ (if *empty-attribute-syntax*
+ ` @attr`
+ ` @attr=@aqc@attr@aqc`))
+ ((or noesc *cl-who-compat*) ;; no escaping in CL-WHO compat mode
+ ` @attr=@aqc@(tostringp eval)@aqc`)
+ (t ` @attr=@aqc@(html-encode (tostringp eval))@aqc`)))
+ ;; For non-constant, do the same things as above but at runtime
+ ^(let ((,=var= ,val))
+ (cond
+ ((null ,=var=))
+ ((eq ,=var= t)
+ (str ,(if *empty-attribute-syntax*
+ ^` @,attr`
+ ^` @,attr=@,aqc@,attr@,aqc`)))
+ (t
+ ,(if (or noesc *cl-who-compat*)
+ ^(str ` @,attr=@,aqc@{,=var=}@,aqc`)
+ ^(str ` @,attr=@,aqc@(html-encode ,=var=)@,aqc`)))))))))))
;; Used by process-tag to convert `HTML' into a list
;; of strings. tag is a keyword symbol naming the outer tag, attr-list