Skip to content

Commit f770e37

Browse files
committed
Add subclasses of tag
1 parent 83e495b commit f770e37

File tree

3 files changed

+26
-20
lines changed

3 files changed

+26
-20
lines changed

hsx-test.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111
(#:hsx-test . #:hsx-test/hsx)
1212
(#:escaper-test . #:hsx-test/escaper)
1313
(#:group-test . #:hsx-test/group))
14-
:num-checks 42)
14+
:num-checks 44)

src/element.lisp

+23-19
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
(:export #:element
1010
#:tag
1111
#:html-tag
12+
#:self-closing-tag
13+
#:non-escaping-tag
1214
#:fragment
1315
#:component
1416
#:create-element
@@ -36,6 +38,10 @@
3638

3739
(defclass html-tag (tag) ())
3840

41+
(defclass self-closing-tag (tag) ())
42+
43+
(defclass non-escaping-tag (tag) ())
44+
3945
(defclass fragment (tag) ())
4046

4147
(defclass component (element) ())
@@ -47,6 +53,8 @@
4753
(cond ((functionp type) 'component)
4854
((eq type :<>) 'fragment)
4955
((eq type :html) 'html-tag)
56+
((self-closing-tag-p type) 'self-closing-tag)
57+
((non-escaping-tag-p type) 'non-escaping-tag)
5058
((keywordp type) 'tag)
5159
(t (error "element-type must be a keyword or a function.")))
5260
:type type
@@ -69,9 +77,7 @@
6977
(write element :stream stream :pretty pretty)))
7078

7179
(defmethod print-object ((element tag) stream)
72-
(with-accessors ((type element-type)
73-
(props element-props)
74-
(children element-children)) element
80+
(with-slots (type props children) element
7581
(let ((type-str (string-downcase type))
7682
(props-str (render-props props)))
7783
(if children
@@ -82,15 +88,13 @@
8288
"~@<<~a~a>~2I~:_~<~a~^~:@_~:>~0I~_</~a>~:>")
8389
type-str
8490
props-str
85-
(escape-children type children)
91+
(render-children element)
8692
type-str)
87-
(format stream
88-
(if (self-closing-tag-p type)
89-
"<~a~a>"
90-
"<~a~a></~a>")
91-
type-str
92-
props-str
93-
type-str)))))
93+
(format stream "<~a~a></~a>" type-str props-str type-str)))))
94+
95+
(defmethod print-object ((element self-closing-tag) stream)
96+
(with-slots (type props) element
97+
(format stream "<~a~a>" (string-downcase type) (render-props props))))
9498

9599
(defun render-props (props)
96100
(with-output-to-string (stream)
@@ -106,20 +110,22 @@
106110
key-str
107111
(escape-html-attribute value)))))))
108112

109-
(defun escape-children (type children)
113+
(defmethod render-children ((element tag))
110114
(mapcar (lambda (child)
111-
(if (and (not (non-escaping-tag-p type))
112-
(stringp child))
115+
(if (stringp child)
113116
(escape-html-text-content child)
114117
child))
115-
children))
118+
(element-children element)))
119+
120+
(defmethod render-children ((element non-escaping-tag))
121+
(element-children element))
116122

117123
(defmethod print-object ((element html-tag) stream)
118124
(format stream "<!DOCTYPE html>~%")
119125
(call-next-method))
120126

121127
(defmethod print-object ((element fragment) stream)
122-
(with-accessors ((children element-children)) element
128+
(with-slots (children) element
123129
(if children
124130
(format stream
125131
(if (rest children)
@@ -131,9 +137,7 @@
131137
(print-object (expand-component element) stream))
132138

133139
(defmethod expand-component ((element component))
134-
(with-accessors ((type element-type)
135-
(props element-props)
136-
(children element-children)) element
140+
(with-slots (type props children) element
137141
(apply type (merge-children-into-props props children))))
138142

139143
(defun merge-children-into-props (props children)

tests/element.lisp

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
(test element-class
1616
(is (typep (create-element :div nil nil) 'tag))
1717
(is (typep (create-element :html nil nil) 'html-tag))
18+
(is (typep (create-element :img nil nil) 'self-closing-tag))
19+
(is (typep (create-element :style nil nil) 'non-escaping-tag))
1820
(is (typep (create-element :<> nil nil) 'fragment))
1921
(is (typep (create-element (lambda ()) nil nil) 'component))
2022
(signals error (create-element "div" nil nil)))

0 commit comments

Comments
 (0)