-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
css.clj
73 lines (63 loc) · 2.26 KB
/
css.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
(ns cljfx.css
"Charmingly Simple Styling library allows using clojure data structures to define
application styles.
It adds JVM-wide support for `cljfx-css` URL protocol that can then be used to retrieve
registered style maps as CSS"
(:import [clojure.lang Named]
[java.net URLStreamHandler URL URLConnection]
[java.io ByteArrayInputStream])
(:gen-class :extends java.net.spi.URLStreamHandlerProvider))
(set! *warn-on-reflection* true)
(def ^:private *registry (atom {}))
(defn- write-val [^StringBuilder acc x]
(cond
(instance? Named x) (.append acc (name x))
(sequential? x) (run! #(write-val acc %) x)
:else (.append acc x)))
(defn- write [^StringBuilder acc path m]
(doseq [[k v] m
:when (string? k)
:let [path (str path k)]]
(.append acc path)
(.append acc " {\n")
(doseq [[sub-k sub-v] v
:when (keyword? sub-k)]
(.append acc " ")
(.append acc (name sub-k))
(.append acc ": ")
(write-val acc sub-v)
(.append acc ";\n"))
(.append acc "}\n")
(write acc path v)))
(def ^:private url-protocol "cljfx-css")
(defn- -createURLStreamHandler [this protocol]
(when (= protocol url-protocol)
(proxy [URLStreamHandler] []
(openConnection [^URL url]
(proxy [URLConnection] [url]
(connect [])
(getInputStream []
(let [style (get @*registry (keyword (.getQuery url)))
acc (StringBuilder.)]
(write acc "" style)
(ByteArrayInputStream. (.getBytes (.toString acc) "UTF-8")))))))))
(defn register
"Globally register style map describing CSS with associated keyword identifier
Returns a map with added key `:cljfx.css/url` containing url string pointing to CSS
CSS is created by recursively concatenating string keys starting from root to define
selectors, while using keyword keys in value maps to define rules, for example:
```
{\".button\" {:-fx-text-fill \"#ccc\"
\":hover\" {:-fx-text-fill \"#aaa\"}}}
;; corresponds to this css:
.button {
-fx-text-fill: #ccc;
}
.button:hover {
-fx-text-fill: #aaa;
}
```"
[id m]
(let [css (assoc m ::url (str url-protocol ":?" (symbol id) "#" (hash m)))]
(swap! *registry assoc id css)
css))