Minify props string

This commit is contained in:
paku 2024-10-03 09:54:43 +09:00
parent 6f8df3e00d
commit b430b42699
5 changed files with 61 additions and 33 deletions

View file

@ -2,8 +2,8 @@
:class :package-inferred-system
:pathname "tests"
:depends-on ("rove"
"hsx-test/utils"
"hsx-test/element"
"hsx-test/escaper"
"hsx-test/group"
"hsx-test/hsx")
:perform (test-op (o c) (symbol-call :rove :run c :style :dot)))

View file

@ -1,8 +1,9 @@
(defpackage #:hsx/element
(:use #:cl)
(:import-from #:hsx/escaper
(:import-from #:hsx/utils
#:escape-html-attribute
#:escape-html-text-content)
#:escape-html-text-content
#:minify)
(:import-from #:hsx/group
#:self-closing-tag-p
#:non-escaping-tag-p)
@ -118,18 +119,19 @@
(string-downcase (element-type element)))
(defmethod render-props ((element tag))
(with-output-to-string (stream)
(loop
:for (key value) :on (element-props element) :by #'cddr
:do (let ((key-str (string-downcase key)))
(if (typep value 'boolean)
(format stream
"~@[ ~a~]"
(and value key-str))
(format stream
" ~a=\"~a\""
key-str
(escape-html-attribute value)))))))
(minify
(with-output-to-string (stream)
(loop
:for (key value) :on (element-props element) :by #'cddr
:do (let ((key-str (string-downcase key)))
(if (typep value 'boolean)
(format stream
"~@[ ~a~]"
(and value key-str))
(format stream
" ~a=\"~a\""
key-str
(escape-html-attribute value))))))))
(defmethod render-children ((element tag))
(mapcar (lambda (child)

View file

@ -1,10 +1,11 @@
(defpackage #:hsx/escaper
(defpackage #:hsx/utils
(:use #:cl)
(:import-from #:alexandria
#:alist-hash-table)
(:export #:escape-html-attribute
#:escape-html-text-content))
(in-package #:hsx/escaper)
#:escape-html-text-content
#:minify))
(in-package #:hsx/utils)
(defparameter *text-content-escape-map*
(alist-hash-table
@ -22,7 +23,7 @@
'((#\" . """))))
(defun escape-char (char escape-map)
(or (gethash char escape-map)
(or (gethash char escape-map)
char))
(defun escape-string (string escape-map)
@ -38,3 +39,19 @@
(defun escape-html-attribute (text)
(escape-string text *attribute-escape-map*))
(defun minify (input-string)
(with-output-to-string (out)
(let ((previous-space-p nil))
(loop for char across input-string do
(cond
((whitespace-p char)
(unless previous-space-p
(write-char #\Space out))
(setf previous-space-p t))
(t
(write-char char out)
(setf previous-space-p nil)))))))
(defun whitespace-p (char)
(member char '(#\Space #\Newline #\Tab #\Return) :test #'char=))

View file

@ -1,14 +0,0 @@
(defpackage #:hsx-test/escaper
(:use #:cl
#:rove
#:hsx/escaper))
(in-package #:hsx-test/escaper)
(deftest escaper-test
(testing "escape-html-attribute"
(ok (string= ""foo""
(escape-html-attribute "\"foo\""))))
(testing "escape-html-text-content"
(ok (string= "&<>"'/`="
(escape-html-text-content "&<>\"'/`=")))))

23
tests/utils.lisp Normal file
View file

@ -0,0 +1,23 @@
(defpackage #:hsx-test/utils
(:use #:cl
#:rove
#:hsx/utils))
(in-package #:hsx-test/utils)
(deftest text-util-test
(testing "escape-html-attribute"
(ok (string= "&quot;foo&quot;"
(escape-html-attribute "\"foo\""))))
(testing "escape-html-text-content"
(ok (string= "&amp;&lt;&gt;&quot;&#x27;&#x2F;&grave;&#x3D;"
(escape-html-text-content "&<>\"'/`="))))
(testing "minify"
;; Test with Alpine.js
(ok (string= (minify "{
open: false,
get isOpen() { return this.open },
toggle() { this.open = ! this.open },
}")
"{ open: false, get isOpen() { return this.open }, toggle() { this.open = ! this.open }, }"))))