Skip to content

Commit 78e36db

Browse files
committed
Implement beginning of cljs test suite
Multiple fixes: - data extended dom now provides equality - Provide reification to native nodes or to maps - include a mock xml dom for tests in nashorn - unfortunately, this can't test native dom extension, since xmldom is spotty
1 parent 8ab647e commit 78e36db

15 files changed

Lines changed: 2654 additions & 82 deletions

File tree

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,9 @@
22
modules/xml/target/
33
modules/xml.pull-parser/target/
44
*~
5+
/out/
6+
/node_modules/
7+
/nashorn_code_cache/
8+
/figwheel_server.log
9+
/.nrepl-port
10+
/.cljs_nashorn_repl/

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,39 @@ To elide location information, pass `:location-info false` to the parser:
289289

290290
(parse-str your-input :location-info false)
291291

292+
## Clojurescript support
293+
294+
The Clojurescript implementation uses the same namespace as the Clojure one `clojure.data.xml`.
295+
296+
### Differences from Clojure implementation
297+
298+
data.xml uses native browser dom elements to represent xml. To get back the convenience of treating them as maps, call `(extend-dom-as-data!)`. This extends the native dom node prototypes to Clojurescript collection protocols, such that you can treat them as data.xml parse trees.
299+
300+
Of course, the map format is supported for emitting.
301+
302+
### Missing Features, Patches Welcome
303+
304+
#### Streaming
305+
306+
data.xml on Clojurescript doesn't currently support streaming, hence only the `*-str` variants of `parse`/`emit` are implemented. Those are just wrappers for browser's native xml parsing/printing.
307+
308+
Pull parsing doesn't seem the right solution for Clojurescript, because when code cannot block, the parser has no way of waiting on its input. For this reason, parsing in Clojurescript cannot be based around `event-seq`.
309+
310+
Push parsing, on the other hand should not pose a problem, because when data arrives in a callback, it can be pushed on into the parser. Fortunately, clojure already has a nice push-based pendant for lazy sequences: transducers.
311+
312+
#### Utilities
313+
314+
Some utilities, like `process/*-xmlns`, `prxml/sexp-as-*`, `indent` aren't yet implemented.
315+
316+
#### Immutable updates for dom types
317+
318+
Make `extend-dom-as-data!` also support assoc, ... on dom nodes.
319+
320+
#### Data coercions
321+
322+
323+
324+
292325
## License
293326

294327
Licensed under the [Eclipse Public License](http://www.opensource.org/licenses/eclipse-1.0.php).

dxml-nashorn.global.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
global.console = {
2+
log: print,
3+
warn: print,
4+
error: print
5+
};
6+
global.xmldom = require("xmldom");
7+
global.DOMParser = global.xmldom.DOMParser;
8+
global.XMLSerializer = global.xmldom.XMLSerializer;

package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
3+
"scripts": {
4+
"build": "webpack"
5+
}
6+
7+
, "devDependencies": {
8+
"webpack": "2.1.0-beta.27",
9+
"xmldom" : "0.1.27"
10+
"domino" : ""
11+
}
12+
, "name": "dxml-nashorn-api"
13+
}

pom.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@
4848
</execution>
4949
</executions>
5050
</plugin>
51+
<plugin>
52+
<artifactId>maven-jar-plugin</artifactId>
53+
<version>2.4</version>
54+
<executions>
55+
<execution>
56+
<id>default-jar</id>
57+
<phase>package</phase>
58+
<goals>
59+
<goal>jar</goal>
60+
</goals>
61+
<configuration>
62+
<includes>
63+
<include>**/*.clj</include>
64+
<include>**/*.cljs</include>
65+
<include>**/*.cljc</include>
66+
</includes>
67+
</configuration>
68+
</execution>
69+
</executions>
70+
</plugin>
5171
</plugins>
5272
</build>
5373

project.clj

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
(defproject org.clojure/data.xml "0-UE-DEVELOPMENT"
22
:source-paths ["src/main/clojure"]
33
:test-paths ["src/test/clojure"]
4-
:resource-paths ["src/test/resources"]
5-
:dependencies [[org.clojure/clojure "1.8.0"]])
4+
:resource-paths ["src/test/resources" "target/gen-resources"]
5+
:dependencies [[org.clojure/clojure "1.8.0"]
6+
[org.clojure/clojurescript "1.9.293"]
7+
[com.cemerick/piggieback "0.2.1"]
8+
[org.clojure/tools.nrepl "0.2.12"]
9+
[figwheel-sidecar "0.5.8"]]
10+
:repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]})

src/main/clojure/clojure/data/xml.cljs

Lines changed: 15 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,37 @@
77
[clojure.data.xml.protocols :refer [AsQName]]))
88

99
(export-api
10-
name/parse-qname name/qname-uri name/qname-local name/qname name/to-qname
11-
node/element* node/element node/cdata node/xml-comment)
10+
name/parse-qname name/qname-uri name/qname-local name/qname name/to-qname name/uri-symbol
11+
node/element* node/element node/cdata node/xml-comment node/text-node
12+
node/extend-dom-as-data! node/element-node node/element-data)
1213

1314
(defn canonical-name
1415
"Put (q)name into canonical form as per ns-env"
1516
[n]
1617
(name/canonical-name (qname-uri n) (qname-local n) ""))
1718

18-
;; TODO event-seq
19+
;;;; ## TODO event-seq
20+
;; This probably won't happen due to js' non-blocking semantics
21+
;; Instead, for clojurescript, the machinery around event-seq could be implemented
22+
;; as a transducer stack, such that a push-based source for parser events, like sax-js,
23+
;; could be used.
24+
1925
;; TODO parse (use goog StringBuffer?)
2026

2127
(defn parse-str
2228
"Use DOMParser to parse xml string"
2329
;; TODO detect browser specific parsererror tags
2430
;; see http://stackoverflow.com/questions/11563554/how-do-i-detect-xml-parsing-errors-when-using-javascripts-domparser-in-a-cross
25-
[s & {:keys [content-type on-error]
31+
[s & {:keys [content-type on-error raw]
2632
:or {content-type "text/xml"
2733
on-error #(throw "XML parser error" {:doc % :input s})}}]
2834
(let [dom (. (js/DOMParser.)
2935
(parseFromString s content-type))
3036
doc (.-documentElement dom)]
31-
(if (= "parsererror" (.-nodeName doc))
32-
(on-error doc)
33-
doc)))
37+
(cond (= "parsererror" (.-nodeName doc))
38+
(on-error doc)
39+
raw doc
40+
:else (element-data doc))))
3441

3542
;; TODO emit (use goog StringBuffer?)
3643

@@ -39,68 +46,5 @@
3946
[e & {:keys []}]
4047
(. (js/XMLSerializer.)
4148
(serializeToString
42-
(node/coerce-to-dom e))))
43-
44-
(defn extend-nodes-as-qname! []
45-
(extend-protocol AsQName
46-
js/Element
47-
(qname-local [e] (.-localName e))
48-
(qname-uri [e] (.-namespaceURI e))
49-
js/Attr
50-
(qname-local [e] (.-localName e))
51-
(qname-uri [e] (.-namespaceURI e))))
52-
53-
(defn- as-node [n]
54-
(if (instance? js/Text n)
55-
(.-wholeText n) ;; .-data
56-
n))
57-
58-
(defn extend-dom-as-data! []
59-
(extend-type js/Element
60-
ILookup
61-
(-lookup [el k]
62-
(case k
63-
:tag (name/canonical-name (.-namespaceURI el)
64-
(.-localName el)
65-
"")
66-
:attrs (.-attributes el)
67-
:content (.-childNodes el)
68-
(throw "XML tag has no key" {:key k :el el}))))
69-
(extend-type js/NamedNodeMap
70-
ILookup
71-
(-lookup
72-
([attrs attr]
73-
(if-let [i (.getNamedItemNS attrs (qname-uri attr) (qname-local attr))]
74-
(.-value i)
75-
nil))
76-
([attrs attr not-found]
77-
(if-let [i (.getNamedItemNS attrs (qname-uri attr) (qname-local attr))]
78-
(.-value i)
79-
not-found))))
80-
(extend-type js/NodeList
81-
ISeqable
82-
(-seq [nl] (map as-node (array-seq nl)))
83-
ISequential
84-
ICounted
85-
(-count [nl] (.-length nl))
86-
IIndexed
87-
(-nth
88-
([nl n]
89-
(as-node (aget nl n)))
90-
([nl n nf]
91-
(if (and (<= 0 n) (< n (.-length nl)))
92-
(as-node (aget nl n))
93-
nf)))))
94-
95-
(comment
96-
97-
(extend-dom-as-data!)
98-
(extend-nodes-as-qname!)
49+
(node/element-node e))))
9950

100-
(let [{tag :tag {a1 "{DAV:}a1" a2 "a2" :as attrs} :attrs [c1 c2 c3] :content}
101-
(parse-str "<xml xmlns:d=\"DAV:\" d:a1=\"dav-a1\" a2=\"normal a2\">
102-
Fancy Content <br/> More
103-
</xml>")]
104-
[tag a1 a2 c1 c2 c3])
105-
106-
)

0 commit comments

Comments
 (0)