hsx/src/hsx.lisp

94 lines
3.1 KiB
Common Lisp
Raw Normal View History

2024-05-25 16:26:26 +00:00
(uiop:define-package #:hsx/hsx
(:use #:cl)
(:import-from #:alexandria
2024-05-26 10:48:09 +00:00
#:symbolicate
#:make-keyword)
2024-05-25 16:26:26 +00:00
(:import-from #:hsx/element
#:create-element)
2024-05-27 02:10:11 +00:00
(:export #:defhsx
#:defcomp
2024-05-26 10:48:09 +00:00
#:hsx))
2024-05-25 16:26:26 +00:00
(in-package #:hsx/hsx)
2024-05-26 14:29:30 +00:00
;;;; hsx definitions
2024-05-27 02:10:11 +00:00
(defmacro defhsx (name element-type)
2024-05-25 16:26:26 +00:00
`(defmacro ,name (&body body)
(multiple-value-bind (props children)
(parse-body body)
2024-05-27 02:10:11 +00:00
`(create-element ,',element-type (list ,@props) ,@children))))
(defparameter *builtin-elements* (make-hash-table))
2024-05-25 16:26:26 +00:00
2024-05-26 14:29:30 +00:00
(defmacro define-and-export-builtin-elements (&body names)
2024-05-25 16:26:26 +00:00
`(progn
,@(mapcan (lambda (name)
2024-05-27 02:10:11 +00:00
(list `(defhsx ,name ,(string-downcase name))
2024-05-26 10:48:09 +00:00
`(setf (gethash (make-keyword ',name) *builtin-elements*) t)
2024-05-25 16:26:26 +00:00
`(export ',name)))
names)))
(define-and-export-builtin-elements
2024-05-26 14:29:30 +00:00
; tag-elements
a abbr address area article aside audio b base bdi bdo blockquote
2024-05-25 16:26:26 +00:00
body br button canvas caption cite code col colgroup data datalist
dd del details dfn dialog div dl dt em embed fieldset figcaption
2024-05-26 14:29:30 +00:00
figure footer form h1 h2 h3 h4 h5 h6 head header hr i iframe
2024-05-25 16:26:26 +00:00
img input ins kbd label legend li link main |map| mark meta meter nav
noscript object ol optgroup option output p param picture pre progress
q rp rt ruby s samp script section select small source span strong
style sub summary sup svg table tbody td template textarea tfoot th
2024-05-26 14:29:30 +00:00
thead |time| title tr track u ul var video wbr
; html-tag-element
html
; fragment-element
<>)
2024-05-25 16:26:26 +00:00
(defmacro defcomp (name props &body body)
(let ((%name (symbolicate '% name)))
`(eval-when (:compile-toplevel :load-toplevel :execute)
(defun ,%name ,props
,@body)
2024-05-27 02:10:11 +00:00
(defhsx ,name (fdefinition ',%name)))))
2024-05-26 10:48:09 +00:00
2024-05-26 14:29:30 +00:00
(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)))
;;;; hsx macro to find hsx symbols
(defmacro hsx (&body body)
`(progn
,@(modify-first-leaves body
#'builtin-element-p
(lambda (node)
(find-symbol (string node) :hsx/hsx)))))
2024-05-26 10:48:09 +00:00
(defun modify-first-leaves (tree test result)
(if tree
(cons (let ((first-node (first tree)))
(cond
((listp first-node)
(modify-first-leaves first-node test result))
((funcall test first-node)
(funcall result first-node))
(t first-node)))
(mapcar (lambda (node)
(if (listp node)
(modify-first-leaves node test result)
node))
(rest tree)))))
2024-05-26 14:29:30 +00:00
(defun builtin-element-p (node)
(and (symbolp node)
(gethash (make-keyword node) *builtin-elements*)))