Separate defhsx package from hsx package
This commit is contained in:
parent
8e5f597be6
commit
ead5c408e3
10 changed files with 156 additions and 150 deletions
|
@ -3,6 +3,6 @@
|
||||||
:pathname "tests"
|
:pathname "tests"
|
||||||
:depends-on ("fiveam"
|
:depends-on ("fiveam"
|
||||||
"hsx-test/element"
|
"hsx-test/element"
|
||||||
"hsx-test/hsx"
|
"hsx-test/defhsx"
|
||||||
"hsx-test/hsx-macro")
|
"hsx-test/hsx")
|
||||||
:perform (test-op (op c) (symbol-call :fiveam :run-all-tests)))
|
:perform (test-op (op c) (symbol-call :fiveam :run-all-tests)))
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
(:use #:cl)
|
(:use #:cl)
|
||||||
(:import-from #:alexandria
|
(:import-from #:alexandria
|
||||||
#:make-keyword)
|
#:make-keyword)
|
||||||
(:import-from #:hsx/hsx
|
(:import-from #:hsx/defhsx
|
||||||
#:defhsx))
|
#:defhsx))
|
||||||
(in-package #:hsx/builtin)
|
(in-package #:hsx/builtin)
|
||||||
|
|
||||||
|
|
||||||
(defmacro define-and-export-builtin-elements (&rest names)
|
(defmacro define-and-export-builtin-elements (&rest names)
|
||||||
`(progn
|
`(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
,@(mapcan (lambda (name)
|
,@(mapcan (lambda (name)
|
||||||
(list `(defhsx ,name ,(string-downcase name))
|
(list `(defhsx ,name ,(string-downcase name))
|
||||||
`(export ',name)))
|
`(export ',name)))
|
||||||
|
|
35
src/defhsx.lisp
Normal file
35
src/defhsx.lisp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
(uiop:define-package #:hsx/defhsx
|
||||||
|
(:use #:cl)
|
||||||
|
(:import-from #:alexandria
|
||||||
|
#:symbolicate)
|
||||||
|
(:import-from #:hsx/element
|
||||||
|
#:create-element)
|
||||||
|
(:export #:defhsx
|
||||||
|
#:defcomp))
|
||||||
|
(in-package #:hsx/defhsx)
|
||||||
|
|
||||||
|
|
||||||
|
(defmacro defhsx (name element-type)
|
||||||
|
`(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
(defmacro ,name (&body body)
|
||||||
|
(multiple-value-bind (props children)
|
||||||
|
(parse-body body)
|
||||||
|
`(create-element ,',element-type (list ,@props) ,@children)))))
|
||||||
|
|
||||||
|
(defun parse-body (body)
|
||||||
|
(if (keywordp (first body))
|
||||||
|
(loop :for thing :on body :by #'cddr
|
||||||
|
:for (k v) := thing
|
||||||
|
:when (and (keywordp k) v)
|
||||||
|
:append (list k v) :into props
|
||||||
|
:when (not (keywordp k))
|
||||||
|
:return (values props thing)
|
||||||
|
:finally (return (values props nil)))
|
||||||
|
(values nil body)))
|
||||||
|
|
||||||
|
(defmacro defcomp (name props &body body)
|
||||||
|
(let ((%name (symbolicate '% name)))
|
||||||
|
`(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
(defun ,%name ,props
|
||||||
|
,@body)
|
||||||
|
(defhsx ,name (fdefinition ',%name)))))
|
|
@ -7,6 +7,7 @@
|
||||||
#:expand-component))
|
#:expand-component))
|
||||||
(in-package #:hsx/element)
|
(in-package #:hsx/element)
|
||||||
|
|
||||||
|
|
||||||
;;;; class definitions
|
;;;; class definitions
|
||||||
|
|
||||||
(defclass element ()
|
(defclass element ()
|
||||||
|
|
38
src/hsx.lisp
38
src/hsx.lisp
|
@ -1,45 +1,9 @@
|
||||||
(uiop:define-package #:hsx/hsx
|
(uiop:define-package #:hsx/hsx
|
||||||
(:use #:cl)
|
(:use #:cl)
|
||||||
(:import-from #:alexandria
|
(:export #:hsx))
|
||||||
#:symbolicate)
|
|
||||||
(:import-from #:hsx/element
|
|
||||||
#:create-element)
|
|
||||||
(:export #:defhsx
|
|
||||||
#:defcomp
|
|
||||||
#:hsx))
|
|
||||||
(in-package #:hsx/hsx)
|
(in-package #:hsx/hsx)
|
||||||
|
|
||||||
|
|
||||||
;;;; hsx definitions
|
|
||||||
|
|
||||||
(defmacro defhsx (name element-type)
|
|
||||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
||||||
`(defmacro ,name (&body body)
|
|
||||||
(multiple-value-bind (props children)
|
|
||||||
(parse-body body)
|
|
||||||
`(create-element ,',element-type (list ,@props) ,@children)))))
|
|
||||||
|
|
||||||
(defun parse-body (body)
|
|
||||||
(if (keywordp (first body))
|
|
||||||
(loop :for thing :on body :by #'cddr
|
|
||||||
:for (k v) := thing
|
|
||||||
:when (and (keywordp k) v)
|
|
||||||
:append (list k v) :into props
|
|
||||||
:when (not (keywordp k))
|
|
||||||
:return (values props thing)
|
|
||||||
:finally (return (values props nil)))
|
|
||||||
(values nil body)))
|
|
||||||
|
|
||||||
(defmacro defcomp (name props &body body)
|
|
||||||
(let ((%name (symbolicate '% name)))
|
|
||||||
`(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
||||||
(defun ,%name ,props
|
|
||||||
,@body)
|
|
||||||
(defhsx ,name (fdefinition ',%name)))))
|
|
||||||
|
|
||||||
|
|
||||||
;;;; hsx macro to find hsx symbols
|
|
||||||
|
|
||||||
(defmacro hsx (&body form)
|
(defmacro hsx (&body form)
|
||||||
(when (not (= (length form) 1))
|
(when (not (= (length form) 1))
|
||||||
(error "The body of the hsx macro must be a single form."))
|
(error "The body of the hsx macro must be a single form."))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(uiop:define-package :hsx
|
(uiop:define-package :hsx
|
||||||
(:nicknames #:hsx/main)
|
(:nicknames #:hsx/main)
|
||||||
(:use #:cl)
|
(:use #:cl)
|
||||||
(:use-reexport #:hsx/hsx)
|
(:use-reexport #:hsx/defhsx)
|
||||||
(:import-from #:hsx/builtin))
|
(:import-from #:hsx/builtin)
|
||||||
|
(:use-reexport #:hsx/hsx))
|
||||||
(in-package :hsx)
|
(in-package :hsx)
|
||||||
|
|
88
tests/defhsx.lisp
Normal file
88
tests/defhsx.lisp
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
(defpackage #:hsx-test/defhsx
|
||||||
|
(:use #:cl
|
||||||
|
#:fiveam
|
||||||
|
#:hsx/defhsx
|
||||||
|
#:hsx/builtin)
|
||||||
|
(:import-from #:hsx/element
|
||||||
|
#:create-element))
|
||||||
|
(in-package #:hsx-test/defhsx)
|
||||||
|
|
||||||
|
|
||||||
|
(def-suite defhsx-test)
|
||||||
|
(in-suite defhsx-test)
|
||||||
|
|
||||||
|
(test empty-hsx
|
||||||
|
(is (equal (macroexpand-1
|
||||||
|
'(div))
|
||||||
|
'(create-element
|
||||||
|
"div"
|
||||||
|
(list)))))
|
||||||
|
|
||||||
|
(test hsx-with-props
|
||||||
|
(is (equal (macroexpand-1
|
||||||
|
'(div :prop1 "value1" :prop2 "value2"))
|
||||||
|
'(create-element
|
||||||
|
"div"
|
||||||
|
(list :prop1 "value1" :prop2 "value2")))))
|
||||||
|
|
||||||
|
(test hsx-with-children
|
||||||
|
(is (equal (macroexpand-1
|
||||||
|
'(div
|
||||||
|
"child1"
|
||||||
|
"child2"))
|
||||||
|
'(create-element
|
||||||
|
"div"
|
||||||
|
(list)
|
||||||
|
"child1"
|
||||||
|
"child2"))))
|
||||||
|
|
||||||
|
(test hsx-with-props-and-children
|
||||||
|
(is (equal (macroexpand-1
|
||||||
|
'(div :prop1 "value1" :prop2 "value2"
|
||||||
|
"child1"
|
||||||
|
"child2"))
|
||||||
|
'(create-element
|
||||||
|
"div"
|
||||||
|
(list :prop1 "value1" :prop2 "value2")
|
||||||
|
"child1"
|
||||||
|
"child2"))))
|
||||||
|
|
||||||
|
(defhsx custom "custom")
|
||||||
|
|
||||||
|
(test hsx-for-custom-tag-element
|
||||||
|
(is (equal (macroexpand-1
|
||||||
|
'(custom :prop1 "value1" :prop2 "value2"
|
||||||
|
"child1"
|
||||||
|
"child2"))
|
||||||
|
'(create-element
|
||||||
|
"custom"
|
||||||
|
(list :prop1 "value1" :prop2 "value2")
|
||||||
|
"child1"
|
||||||
|
"child2"))))
|
||||||
|
|
||||||
|
(defhsx comp1 #'%comp1)
|
||||||
|
(defun %comp1 (&key prop1 prop2 children)
|
||||||
|
(declare (ignore prop1 prop2 children)))
|
||||||
|
|
||||||
|
(defcomp comp2 (&key prop1 prop2 children)
|
||||||
|
(declare (ignore prop1 prop2 children)))
|
||||||
|
|
||||||
|
(test hsx-for-component-element
|
||||||
|
(is (equal (macroexpand-1
|
||||||
|
'(comp1 :prop1 "value1" :prop2 "value2"
|
||||||
|
"child1"
|
||||||
|
"child2"))
|
||||||
|
'(create-element
|
||||||
|
#'%comp1
|
||||||
|
(list :prop1 "value1" :prop2 "value2")
|
||||||
|
"child1"
|
||||||
|
"child2")))
|
||||||
|
(is (equal (macroexpand-1
|
||||||
|
'(comp2 :prop1 "value1" :prop2 "value2"
|
||||||
|
"child1"
|
||||||
|
"child2"))
|
||||||
|
'(create-element
|
||||||
|
(fdefinition '%comp2)
|
||||||
|
(list :prop1 "value1" :prop2 "value2")
|
||||||
|
"child1"
|
||||||
|
"child2"))))
|
|
@ -4,6 +4,7 @@
|
||||||
#:hsx/element))
|
#:hsx/element))
|
||||||
(in-package #:hsx-test/element)
|
(in-package #:hsx-test/element)
|
||||||
|
|
||||||
|
|
||||||
(def-suite element-test)
|
(def-suite element-test)
|
||||||
(in-suite element-test)
|
(in-suite element-test)
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
(defpackage #:hsx-test/hsx-macro
|
|
||||||
(:use #:cl
|
|
||||||
#:fiveam)
|
|
||||||
(:import-from #:hsx/element
|
|
||||||
#:element-type
|
|
||||||
#:element-children)
|
|
||||||
(:import-from #:hsx/hsx
|
|
||||||
#:hsx
|
|
||||||
#:defcomp))
|
|
||||||
(in-package #:hsx-test/hsx-macro)
|
|
||||||
|
|
||||||
(def-suite hsx-macro-test)
|
|
||||||
(in-suite hsx-macro-test)
|
|
||||||
|
|
||||||
(defcomp div (&rest props)
|
|
||||||
(declare (ignore props))
|
|
||||||
"This is fake!")
|
|
||||||
|
|
||||||
(defcomp p (&rest props)
|
|
||||||
(declare (ignore props))
|
|
||||||
"This is fake!")
|
|
||||||
|
|
||||||
(test find-symbols
|
|
||||||
(let ((fake-elm (div :prop "value"
|
|
||||||
(p "brah"))))
|
|
||||||
(is (eql (element-type fake-elm) #'%div)
|
|
||||||
(eql (element-type (first (element-children fake-elm))) #'%p)))
|
|
||||||
(let ((true-elm (hsx (div :prop "value"
|
|
||||||
(p "brah")))))
|
|
||||||
(is (equal (element-type true-elm) "div")
|
|
||||||
(equal (element-type (first (element-children true-elm))) "p"))))
|
|
|
@ -1,87 +1,33 @@
|
||||||
(defpackage #:hsx-test/hsx
|
(defpackage #:hsx-test/hsx
|
||||||
(:use #:cl
|
(:use #:cl
|
||||||
#:fiveam
|
#:fiveam
|
||||||
#:hsx/hsx
|
#:hsx/hsx)
|
||||||
#:hsx/builtin)
|
|
||||||
(:import-from #:hsx/element
|
(:import-from #:hsx/element
|
||||||
#:create-element))
|
#:element-type
|
||||||
|
#:element-children)
|
||||||
|
(:import-from #:hsx/defhsx
|
||||||
|
#:defcomp)
|
||||||
|
(:import-from #:hsx/builtin))
|
||||||
(in-package #:hsx-test/hsx)
|
(in-package #:hsx-test/hsx)
|
||||||
|
|
||||||
|
|
||||||
(def-suite hsx-test)
|
(def-suite hsx-test)
|
||||||
(in-suite hsx-test)
|
(in-suite hsx-test)
|
||||||
|
|
||||||
(test empty-hsx
|
(defcomp div (&rest props)
|
||||||
(is (equal (macroexpand-1
|
(declare (ignore props))
|
||||||
'(div))
|
"This is fake!")
|
||||||
'(create-element
|
|
||||||
"div"
|
|
||||||
(list)))))
|
|
||||||
|
|
||||||
(test hsx-with-props
|
(defcomp p (&rest props)
|
||||||
(is (equal (macroexpand-1
|
(declare (ignore props))
|
||||||
'(div :prop1 "value1" :prop2 "value2"))
|
"This is fake!")
|
||||||
'(create-element
|
|
||||||
"div"
|
|
||||||
(list :prop1 "value1" :prop2 "value2")))))
|
|
||||||
|
|
||||||
(test hsx-with-children
|
(test find-symbols
|
||||||
(is (equal (macroexpand-1
|
(let ((fake-elm (div :prop "value"
|
||||||
'(div
|
(p "brah"))))
|
||||||
"child1"
|
(is (eql (element-type fake-elm) #'%div)
|
||||||
"child2"))
|
(eql (element-type (first (element-children fake-elm))) #'%p)))
|
||||||
'(create-element
|
(let ((true-elm (hsx (div :prop "value"
|
||||||
"div"
|
(p "brah")))))
|
||||||
(list)
|
(is (equal (element-type true-elm) "div")
|
||||||
"child1"
|
(equal (element-type (first (element-children true-elm))) "p"))))
|
||||||
"child2"))))
|
|
||||||
|
|
||||||
(test hsx-with-props-and-children
|
|
||||||
(is (equal (macroexpand-1
|
|
||||||
'(div :prop1 "value1" :prop2 "value2"
|
|
||||||
"child1"
|
|
||||||
"child2"))
|
|
||||||
'(create-element
|
|
||||||
"div"
|
|
||||||
(list :prop1 "value1" :prop2 "value2")
|
|
||||||
"child1"
|
|
||||||
"child2"))))
|
|
||||||
|
|
||||||
(defhsx custom "custom")
|
|
||||||
|
|
||||||
(test hsx-for-custom-tag-element
|
|
||||||
(is (equal (macroexpand-1
|
|
||||||
'(custom :prop1 "value1" :prop2 "value2"
|
|
||||||
"child1"
|
|
||||||
"child2"))
|
|
||||||
'(create-element
|
|
||||||
"custom"
|
|
||||||
(list :prop1 "value1" :prop2 "value2")
|
|
||||||
"child1"
|
|
||||||
"child2"))))
|
|
||||||
|
|
||||||
(defhsx comp1 #'%comp1)
|
|
||||||
(defun %comp1 (&key prop1 prop2 children)
|
|
||||||
(declare (ignore prop1 prop2 children)))
|
|
||||||
|
|
||||||
(defcomp comp2 (&key prop1 prop2 children)
|
|
||||||
(declare (ignore prop1 prop2 children)))
|
|
||||||
|
|
||||||
(test hsx-for-component-element
|
|
||||||
(is (equal (macroexpand-1
|
|
||||||
'(comp1 :prop1 "value1" :prop2 "value2"
|
|
||||||
"child1"
|
|
||||||
"child2"))
|
|
||||||
'(create-element
|
|
||||||
#'%comp1
|
|
||||||
(list :prop1 "value1" :prop2 "value2")
|
|
||||||
"child1"
|
|
||||||
"child2")))
|
|
||||||
(is (equal (macroexpand-1
|
|
||||||
'(comp2 :prop1 "value1" :prop2 "value2"
|
|
||||||
"child1"
|
|
||||||
"child2"))
|
|
||||||
'(create-element
|
|
||||||
(fdefinition '%comp2)
|
|
||||||
(list :prop1 "value1" :prop2 "value2")
|
|
||||||
"child1"
|
|
||||||
"child2"))))
|
|
||||||
|
|
Loading…
Reference in a new issue