Remove ASCII-based escaping
This commit is contained in:
parent
a637a2edbc
commit
050c14209c
3 changed files with 19 additions and 55 deletions
23
README.md
23
README.md
|
@ -9,7 +9,7 @@ It's
|
||||||
- Powerful: help you define reusable and composable components, like that in React
|
- Powerful: help you define reusable and composable components, like that in React
|
||||||
- Modern: focus only on HTML5
|
- Modern: focus only on HTML5
|
||||||
|
|
||||||
# Changes from Flute
|
# Differences from Flute
|
||||||
|
|
||||||
- Added:
|
- Added:
|
||||||
- React-like fragment `(<> ...)`. It lets you group elements without a wrapper element.
|
- 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.
|
- Element functions are wrapped in macros for natural indentation.
|
||||||
- Bugfix. https://github.com/ailisp/flute/issues/5, https://github.com/ailisp/flute/issues/7
|
- Bugfix. https://github.com/ailisp/flute/issues/5, https://github.com/ailisp/flute/issues/7
|
||||||
- Removed:
|
- 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
|
# Getting started
|
||||||
|
|
||||||
|
@ -242,7 +243,7 @@ The `HTML` element is a little special, it's with `<!DOCTYPE html>` prefix to ma
|
||||||
;;
|
;;
|
||||||
;; Create a attrs aoject, given an alist of (:attr . "attr-value") pair.
|
;; Create a attrs aoject, given an alist of (:attr . "attr-value") pair.
|
||||||
;; Attribute values (cdr of each element in alist) will be escaped if
|
;; 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
|
;; Function COPY-ATTRS ATTRS
|
||||||
;;
|
;;
|
||||||
|
@ -304,15 +305,11 @@ The `HTML` element is a little special, it's with `<!DOCTYPE html>` prefix to ma
|
||||||
```lisp
|
```lisp
|
||||||
;; Variable *ESCAPE-HTML*
|
;; Variable *ESCAPE-HTML*
|
||||||
;;
|
;;
|
||||||
;; Specify the escape option when generate html, can be :UTF8, :ASCII, :ATTR or NIL.
|
;; Specify the escape option when generate html with UTF-8, can be t or NIL.
|
||||||
;; If :UTF8, escape only #\<, #\> and #\& in body, and \" in attribute keys. #\' will
|
;; 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
|
;; in attribute keys will not be escaped since piccolo will always use double quote for
|
||||||
;; attribute keys.
|
;; 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.
|
;; 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 <b>text</b>")
|
|
||||||
;; All the escapes are done in element creation time.
|
;; All the escapes are done in element creation time.
|
||||||
|
|
||||||
;; Function ESCAPE-STRING STRING TEST
|
;; Function ESCAPE-STRING STRING TEST
|
||||||
|
@ -320,17 +317,11 @@ The `HTML` element is a little special, it's with `<!DOCTYPE html>` prefix to ma
|
||||||
;; Escape the STRING if it's a STRING and escaping all charaters C that satisfied
|
;; Escape the STRING if it's a STRING and escaping all charaters C that satisfied
|
||||||
;; (FUNCALL TEST C). Return the new STRING after escape.
|
;; (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 T if CHAR is a CHARACTER that need to be escaped when HTML is UTF-8 encoded.
|
||||||
;; Return NIL otherwise.
|
;; 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
|
;; Function ATTR-VALUE-ESCAPE-CHAR-P CHAR
|
||||||
;;
|
;;
|
||||||
;; Return T if CHAR is a CHARACTER that need to be escaped when as an attribute value.
|
;; Return T if CHAR is a CHARACTER that need to be escaped when as an attribute value.
|
||||||
|
|
|
@ -1,32 +1,18 @@
|
||||||
(uiop:define-package #:piccolo/escape
|
(uiop:define-package #:piccolo/escape
|
||||||
(:use #:cl)
|
(:use #:cl)
|
||||||
(:export #:*escape-html*
|
(:export #:*escape-html*
|
||||||
#:utf8-html-escape-char-p
|
#:html-escape-char-p
|
||||||
#:ascii-html-escape-char-p
|
|
||||||
#:attr-value-escape-char-p
|
#:attr-value-escape-char-p
|
||||||
#:escape-string
|
#:escape-string
|
||||||
#:escape-attrs-alist
|
#:escape-attrs-alist
|
||||||
#:escape-children))
|
#:escape-children))
|
||||||
(in-package #:piccolo/escape)
|
(in-package #:piccolo/escape)
|
||||||
|
|
||||||
(defparameter *escape-html* :utf8
|
(defparameter *escape-html* t)
|
||||||
"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 <b>text</b>\")")
|
|
||||||
|
|
||||||
(defun utf8-html-escape-char-p (char)
|
(defun html-escape-char-p (char)
|
||||||
(find 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)
|
(defun attr-value-escape-char-p (char)
|
||||||
(eql 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)
|
(if (stringp string)
|
||||||
(with-output-to-string (s)
|
(with-output-to-string (s)
|
||||||
(loop
|
(loop
|
||||||
for c across string
|
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))
|
string))
|
||||||
|
|
||||||
(defun escape-attrs-alist (alist)
|
(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)
|
(defun escape-children (children)
|
||||||
(mapcar (lambda (child)
|
(mapcar (lambda (child)
|
||||||
(if (stringp child)
|
(if (stringp child)
|
||||||
(case *escape-html*
|
(escape-string child #'html-escape-char-p)
|
||||||
(:utf8 (escape-string child))
|
|
||||||
(:ascii (escape-string child #'ascii-html-escape-char-p))
|
|
||||||
(otherwise child))
|
|
||||||
child))
|
child))
|
||||||
children))
|
children))
|
||||||
|
|
|
@ -178,11 +178,7 @@
|
||||||
(:data . "'<>")) ))
|
(:data . "'<>")) ))
|
||||||
(is (equal escaped-attrs-alist (attrs-alist (element-attrs (new-a)))))
|
(is (equal escaped-attrs-alist (attrs-alist (element-attrs (new-a)))))
|
||||||
(let ((*escape-html* nil))
|
(let ((*escape-html* nil))
|
||||||
(is (equal *a-attrs* (attrs-alist (element-attrs (new-a))))))
|
(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))))))))
|
|
||||||
|
|
||||||
(test escape-children
|
(test escape-children
|
||||||
(let ((a (new-a)))
|
(let ((a (new-a)))
|
||||||
|
@ -191,15 +187,7 @@
|
||||||
(is (string= "child'<>".html" (attr (element-attrs (third (element-children a))) :href)))
|
(is (string= "child'<>".html" (attr (element-attrs (third (element-children a))) :href)))
|
||||||
(is (string= "child'<>\"" (first (element-children (third (element-children a))))))
|
(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)) (second (element-children (third (element-children a))))))
|
||||||
(is (string= (string (code-char 128)) (fourth (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))))))
|
|
||||||
|
|
||||||
(in-suite attr-access)
|
(in-suite attr-access)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue