-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathcss.clj
More file actions
79 lines (63 loc) · 2.17 KB
/
css.clj
File metadata and controls
79 lines (63 loc) · 2.17 KB
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
(ns shadow.css
(:require
[shadow.css.specs :as s]
[clojure.string :as str]))
(def class-defs-ref
(atom {}))
;; for clojure we just do lookups at runtime
;; by default is empty but in case something has minified the css
;; it can provide those lookups and put them in the class-defs-ref above
(defn get-class [class]
(get @class-defs-ref class class))
(defmacro css
"generates css classnames
using a subset of Clojure/EDN to define css rules, no dynamic code allowed whatsoever"
[& body]
;; FIXME: errors are not pretty
(s/conform! &form)
(let [{:keys [line column]}
(meta &form)
ns-str
(str *ns*)
;; this must generate a unique identifier right here
;; using only information that can be taken from the css form
;; itself. It must not look at any other location and the id
;; generated must be deterministic.
;; this unfortunately makes it pretty much unusable in the REPL
;; this is fine since there is no need for CSS in the REPL
;; but may end up emitting invalid references in code
;; which again is fine in JS since it'll just be undefined
css-id
(s/generate-id (vec body))
passthrough
(->> body
(filter string?)
(str/join " "))]
;; using analyzer data is hard to combine with CLJ data
;; so instead just using an external thing that finds (css ...) calls
;; and generates the stuff we need
#_class-def
#_(assoc conformed
:ns (symbol ns-str)
:line line
:column column
:css-id css-id)
;; FIXME: no idea what to do about self-host yet
(if-not (:ns &env)
(if (seq passthrough)
`(str ~(str passthrough " ") (get-class ~css-id))
`(get-class ~css-id))
(if (seq passthrough)
`(~'js* "(~{} + shadow.css.sel(~{}))" ~(str passthrough " ") ~css-id)
(with-meta
`(~'js* "(shadow.css.sel(~{}))" ~css-id)
(assoc (meta &form) :tag 'shadow.css/css-id)
)))))
(comment
(require 'clojure.pprint)
@class-defs-ref
(clojure.pprint/pprint
(macroexpand
'(css :foo
"yo" {:hello "world"})
)))