From 050c14209c303de497a2c94896c11dcea33a4981 Mon Sep 17 00:00:00 2001 From: paku Date: Sat, 10 Feb 2024 21:02:45 +0900 Subject: [PATCH] Remove ASCII-based escaping --- README.md | 23 +++++++---------------- src/escape.lisp | 35 ++++++++++------------------------- t/piccolo.lisp | 16 ++-------------- 3 files changed, 19 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index ee387c5..fd20629 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ It's - Powerful: help you define reusable and composable components, like that in React - Modern: focus only on HTML5 -# Changes from Flute +# Differences from Flute - Added: - React-like fragment `(<> ...)`. It lets you group elements without a wrapper element. @@ -18,7 +18,8 @@ It's - Element functions are wrapped in macros for natural indentation. - Bugfix. https://github.com/ailisp/flute/issues/5, https://github.com/ailisp/flute/issues/7 - Removed: - - CSS style id and class attributes (e.g. `div#id.class`) + - Attributes like CSS selectors (e.g. `div#id.class`) + - ASCII-based escaping. Piccolo only supports UTF-8. # Getting started @@ -242,7 +243,7 @@ The `HTML` element is a little special, it's with `` prefix to ma ;; ;; Create a attrs aoject, given an alist of (:attr . "attr-value") pair. ;; Attribute values (cdr of each element in alist) will be escaped if -;; *ESCAPE-HTML* is not NIL +;; *ESCAPE-HTML* is t. ;; Function COPY-ATTRS ATTRS ;; @@ -304,15 +305,11 @@ The `HTML` element is a little special, it's with `` prefix to ma ```lisp ;; Variable *ESCAPE-HTML* ;; -;; Specify the escape option when generate html, can be :UTF8, :ASCII, :ATTR or NIL. -;; If :UTF8, escape only #\<, #\> and #\& in body, and \" in attribute keys. #\' will +;; Specify the escape option when generate html with UTF-8, can be t or NIL. +;; If t, escape only #\<, #\> and #\& in body, and \" in attribute keys. #\' will ;; in attribute keys will not be escaped since piccolo will always use double quote for ;; attribute keys. -;; If :ASCII, besides what escaped in :UTF8, also escape all non-ascii characters. -;; If :ATTR, only #\" in attribute values will be escaped. ;; If NIL, nothing is escaped and programmer is responsible to escape elements properly. -;; When given :ASCII and :ATTR, it's possible to insert html text as a children, e.g. -;; (div :id "container" "Some text") ;; All the escapes are done in element creation time. ;; Function ESCAPE-STRING STRING TEST @@ -320,17 +317,11 @@ The `HTML` element is a little special, it's with `` prefix to ma ;; Escape the STRING if it's a STRING and escaping all charaters C that satisfied ;; (FUNCALL TEST C). Return the new STRING after escape. -;; Function UTF8-HTML-ESCAPE-CHAR-P CHAR +;; Function HTML-ESCAPE-CHAR-P CHAR ;; ;; Return T if CHAR is a CHARACTER that need to be escaped when HTML is UTF-8 encoded. ;; Return NIL otherwise. -;; Function ASCII-HTML-ESCAPE-CHAR-P CHAR -;; -;; Return T if CHAR is a CHARACTER that need to be escaped when HTML is ASCII encoded. -;; Return NIL otherwise. - - ;; Function ATTR-VALUE-ESCAPE-CHAR-P CHAR ;; ;; Return T if CHAR is a CHARACTER that need to be escaped when as an attribute value. diff --git a/src/escape.lisp b/src/escape.lisp index 67ae0be..a340c68 100644 --- a/src/escape.lisp +++ b/src/escape.lisp @@ -1,32 +1,18 @@ (uiop:define-package #:piccolo/escape (:use #:cl) (:export #:*escape-html* - #:utf8-html-escape-char-p - #:ascii-html-escape-char-p + #:html-escape-char-p #:attr-value-escape-char-p #:escape-string #:escape-attrs-alist #:escape-children)) (in-package #:piccolo/escape) -(defparameter *escape-html* :utf8 - "Specify the escape option when generate html, can be :UTF8, :ASCII, :ATTR or NIL. -If :UTF8, escape only #\<, #\> and #\& in body, and \" in attribute keys. #\' will -in attribute keys will not be escaped since piccolo will always use double quote for -attribute keys. -If :ASCII, besides what escaped in :UTF8, also escape all non-ascii characters. -If :ATTR, only #\" in attribute values will be escaped. -If NIL, nothing is escaped and programmer is responsible to escape elements properly. -When given :ASCII and :ATTR, it's possible to insert html text as a children, e.g. -(div :id \"container\" \"Some text\")") +(defparameter *escape-html* t) -(defun utf8-html-escape-char-p (char) +(defun html-escape-char-p (char) (find char "<>&")) -(defun ascii-html-escape-char-p (char) - (or (utf8-html-escape-char-p char) - (> (char-code char) 127))) - (defun attr-value-escape-char-p (char) (eql char #\")) @@ -35,16 +21,18 @@ When given :ASCII and :ATTR, it's possible to insert html text as a children, e. (#\< "<") (#\> ">") (#\& "&") - (#\' "'") (#\" """) - (t (format nil "&#~d;" (char-code char))))) + (t (error "Escaped character is undefined: ~a" char)))) -(defun escape-string (string &optional (test #'utf8-html-escape-char-p)) +(defun escape-string (string test) (if (stringp string) (with-output-to-string (s) (loop for c across string - do (write (if (funcall test c) (escape-char c) c) :stream s :escape nil))) + do (write (if (funcall test c) + (escape-char c) + c) + :stream s :escape nil))) string)) (defun escape-attrs-alist (alist) @@ -56,9 +44,6 @@ When given :ASCII and :ATTR, it's possible to insert html text as a children, e. (defun escape-children (children) (mapcar (lambda (child) (if (stringp child) - (case *escape-html* - (:utf8 (escape-string child)) - (:ascii (escape-string child #'ascii-html-escape-char-p)) - (otherwise child)) + (escape-string child #'html-escape-char-p) child)) children)) diff --git a/t/piccolo.lisp b/t/piccolo.lisp index 86df663..9c95633 100644 --- a/t/piccolo.lisp +++ b/t/piccolo.lisp @@ -178,11 +178,7 @@ (:data . "'<>")) )) (is (equal escaped-attrs-alist (attrs-alist (element-attrs (new-a))))) (let ((*escape-html* nil)) - (is (equal *a-attrs* (attrs-alist (element-attrs (new-a)))))) - (let ((*escape-html* :attr)) - (is (equal escaped-attrs-alist (attrs-alist (element-attrs (new-a)))))) - (let ((*escape-html* :ascii)) - (is (equal escaped-attrs-alist (attrs-alist (element-attrs (new-a)))))))) + (is (equal *a-attrs* (attrs-alist (element-attrs (new-a)))))))) (test escape-children (let ((a (new-a))) @@ -191,15 +187,7 @@ (is (string= "child'<>".html" (attr (element-attrs (third (element-children a))) :href))) (is (string= "child'<>\"" (first (element-children (third (element-children a)))))) (is (string= (string (code-char 128)) (second (element-children (third (element-children a)))))) - (is (string= (string (code-char 128)) (fourth (element-children a))))) - (let* ((*escape-html* :ascii) - (a (new-a))) - (is (string= "child text 1" (first (element-children a)))) - (is (string= "child text 2 <br> &" (second (element-children a)))) - (is (string= "child'<>".html" (attr (element-attrs (third (element-children a))) :href))) - (is (string= "child'<>\"" (first (element-children (third (element-children a)))))) - (is (string= "€" (second (element-children (third (element-children a)))))) - (is (string= "€" (fourth (element-children a)))))) + (is (string= (string (code-char 128)) (fourth (element-children a)))))) (in-suite attr-access)