-
-
Notifications
You must be signed in to change notification settings - Fork 81
/
html.cljs
55 lines (49 loc) · 1.46 KB
/
html.cljs
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
(ns portal.ui.html
(:require [clojure.string :as str]
[portal.ui.inspector :as ins]))
(defn- ->style [string]
(persistent!
(reduce
(fn [style rule]
(let [[k v] (str/split rule #":")]
(assoc! style (keyword (str/trim k)) (str/trim v))))
(transient {})
(str/split string #";"))))
(defn- dom->hiccup [opts ^js el]
(let [{:keys [text-handler]} opts]
(case (.-nodeType el)
3 (cond-> (.-wholeText el)
text-handler
text-handler)
1 (let [attrs (.-attributes el)]
(into
[(keyword (str/lower-case (.-tagName el)))
(persistent!
(reduce
(fn [attrs ^js attr]
(let [k (keyword (.-name attr))]
(assoc! attrs k
(case k
:style (->style (.-value attr))
(.-value attr)))))
(transient {})
attrs))]
(map (partial dom->hiccup opts))
(.-childNodes el))))))
(defn- parse-dom [string]
(-> (js/DOMParser.)
(.parseFromString string "text/html")
(.getElementsByTagName "body")
(aget 0)
(.-childNodes)))
(defn parse-html
([html]
(parse-html html nil))
([html opts]
(into [:<>]
(map (partial dom->hiccup opts))
(parse-dom html))))
(def ^:private opts
{:text-handler
(fn [text] [ins/highlight-words text])})
(defn html+ [html] (parse-html html opts))