-
Notifications
You must be signed in to change notification settings - Fork 16
/
parser.clj
81 lines (72 loc) · 2.05 KB
/
parser.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(ns hx.compiler.parser)
(defprotocol IElement
(-parse-element [el args] "Parses an element"))
;; we use a multimethod to dispatch on identity so that consumers
;; can override this for custom values e.g. :<> for React fragments
(defmulti parse-element
(fn [el & more]
(identity el))
:default ::default)
;; if no multimethod for specific el, then apply general parsing rules
(defmethod parse-element
::default
([el & args]
(-parse-element el args)))
;; handle symbols and other forms inside of child seqs
(defn parse-children [form]
(if (vector? form)
(parse-element form)
form))
(defn make-node [el & args]
{:hx/parsed true
:el el
:args args})
(extend-protocol IElement
nil
(-parse-element [_ _]
nil)
java.lang.Long
(-parse-element [n _]
n)
java.lang.String
(-parse-element [s _]
s)
clojure.lang.Keyword
(-parse-element [el args]
(let [props (first args)
children (rest args)]
(apply make-node
(name el)
(if (vector? props) (parse-element props) props)
(into [] (map parse-children children)))))
clojure.lang.APersistentVector
(-parse-element [form _]
(apply parse-element form))
clojure.lang.PersistentList
(-parse-element [form _]
form)
clojure.lang.LazySeq
(-parse-element [form _]
(doall form))
clojure.lang.Symbol
(-parse-element [sym args]
(let [props (first args)
children (rest args)]
(apply make-node
sym
(if (vector? props) (parse-element props) props)
(into [] (map parse-children children))))))
(defn parse [hiccup]
(apply parse-element hiccup))
(def interceptor
{:name :hx.compiler/parser
:enter (fn [context]
(assoc context ::out
(parse (::form context))))})
#_(parse [:div {:id "asdf"} "hi"])
#_(parse [:div [:span "wat"]])
#_(parse [:div [:span "wat"]
[:input {:type "button"} [:i {:id "jkl"} "sup"]]])
#_(parse [:div.thing [:span "wat"]])
#_(parse [:div#thing [:span "wat"]])
#_(parse ['asdf [:span 'jkl "wat"]])