From c376bca835d7068762a7bd6eb28152271bce20b8 Mon Sep 17 00:00:00 2001 From: Edward Knyshov Date: Tue, 17 Nov 2015 02:09:36 +0300 Subject: [PATCH 1/3] update deps, use cljc --- .gitignore | 4 +++- project.clj | 24 ++++--------------- src/hickory/{convert.cljx => convert.cljc} | 0 .../{hiccup_utils.cljx => hiccup_utils.cljc} | 12 +++++----- src/hickory/{render.cljx => render.cljc} | 5 ++-- src/hickory/{select.cljx => select.cljc} | 3 +-- src/hickory/{utils.cljx => utils.cljc} | 12 +++++----- src/hickory/{zip.cljx => zip.cljc} | 0 8 files changed, 22 insertions(+), 38 deletions(-) rename src/hickory/{convert.cljx => convert.cljc} (100%) rename src/hickory/{hiccup_utils.cljx => hiccup_utils.cljc} (97%) rename src/hickory/{render.cljx => render.cljc} (96%) rename src/hickory/{select.cljx => select.cljc} (99%) rename src/hickory/{utils.cljx => utils.cljc} (81%) rename src/hickory/{zip.cljx => zip.cljc} (100%) diff --git a/.gitignore b/.gitignore index 2105c4b..8d812d9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ pom.xml .lein-deps-sum .lein-failures .lein-plugins -.lein-repl-history \ No newline at end of file +.lein-repl-history +/.nrepl-port +/.cljs_rhino_repl/ diff --git a/project.clj b/project.clj index acd577d..b5e6841 100644 --- a/project.clj +++ b/project.clj @@ -5,36 +5,20 @@ :url "http://www.eclipse.org/legal/epl-v10.html"} :source-paths ["src" "target/generated-src"] :test-paths ["target/generated-test"] - :dependencies [[org.clojure/clojure "1.5.1"] + :dependencies [[org.clojure/clojure "1.7.0"] [quoin "0.1.0"] [org.jsoup/jsoup "1.7.1"]] :plugins [[codox "0.6.4"]] :profiles {:dev - {:dependencies [[org.clojure/clojurescript "0.0-2227"]] - :plugins [[lein-cljsbuild "1.0.3"] - [com.keminglabs/cljx "0.4.0"] - [com.cemerick/clojurescript.test "0.3.1"]]}} - :hooks [cljx.hooks] + {:dependencies [[org.clojure/clojurescript "1.7.170"]] + :plugins [[lein-cljsbuild "1.1.1"] + [com.cemerick/clojurescript.test "0.3.3"]]}} :codox {:sources ["src" "target/generated-src"] :output-dir "codox-out" :src-dir-uri "http://github.com/davidsantiago/hickory/blob/master" :src-linenum-anchor-prefix "L"} - - :cljx {:builds [{:source-paths ["src"] - :output-path "target/generated-src" - :rules :clj} - {:source-paths ["src"] - :output-path "target/generated-src" - :rules :cljs} - {:source-paths ["test"] - :output-path "target/generated-test" - :rules :clj} - {:source-paths ["test"] - :output-path "target/generated-test" - :rules :cljs}]} :cljsbuild {:builds [{:source-paths ["target/generated-src" "target/generated-test"] :compiler {:output-to "target/cljs/testable.js"} :optimizations :whitespace :pretty-print true}] :test-commands {"unit-tests" ["phantomjs" :runner "target/cljs/testable.js"]}}) - diff --git a/src/hickory/convert.cljx b/src/hickory/convert.cljc similarity index 100% rename from src/hickory/convert.cljx rename to src/hickory/convert.cljc diff --git a/src/hickory/hiccup_utils.cljx b/src/hickory/hiccup_utils.cljc similarity index 97% rename from src/hickory/hiccup_utils.cljx rename to src/hickory/hiccup_utils.cljc index 29bfee0..d00fa6f 100644 --- a/src/hickory/hiccup_utils.cljx +++ b/src/hickory/hiccup_utils.cljc @@ -11,8 +11,8 @@ (first-idx -1 2) => 2 (first-idx 5 -1) => 5 (first-idx 5 3) => 3" - [#+clj ^long a #+clj ^long b - #+cljs a #+cljs b] + [#?(:clj ^long a) #?(:clj ^long b) + #?(:cljs a) #?(:cljs b)] (if (== a -1) b (if (== b -1) @@ -21,11 +21,11 @@ (defn- index-of ([^String s c] - #+clj (.indexOf s (int c)) - #+cljs (.indexOf s c)) + #?(:clj (.indexOf s (int c))) + #?(:cljs (.indexOf s c))) ([^String s c idx] - #+clj (.indexOf s (int c) (int idx)) - #+cljs (.indexOf s c idx))) + #?(:clj (.indexOf s (int c) (int idx))) + #?(:cljs (.indexOf s c idx)))) (defn- split-keep-trailing-empty "clojure.string/split is a wrapper on java.lang.String/split with the limit diff --git a/src/hickory/render.cljx b/src/hickory/render.cljc similarity index 96% rename from src/hickory/render.cljx rename to src/hickory/render.cljc index d7afa5e..1dd78f4 100644 --- a/src/hickory/render.cljx +++ b/src/hickory/render.cljc @@ -55,9 +55,9 @@ "")) :comment (str "")) - (catch #+clj IllegalArgumentException #+cljs js/Error e + (catch #?(:clj IllegalArgumentException) #?(:cljs js/Error) e (throw - (if (utils/starts-with #+clj (.getMessage e) #+cljs (aget e "message") "No matching clause: ") + (if (utils/starts-with #?(:clj (.getMessage e)) #?(:cljs (aget e "message")) "No matching clause: ") (ex-info (str "Not a valid node: " (pr-str dom)) {:dom dom}) e)))))) @@ -128,4 +128,3 @@ hiccup's." [hiccup-forms] (apply str (map #(render-hiccup-form (hu/normalize-form %)) hiccup-forms))) - diff --git a/src/hickory/select.cljx b/src/hickory/select.cljc similarity index 99% rename from src/hickory/select.cljx rename to src/hickory/select.cljc index 47d639e..bf0a046 100644 --- a/src/hickory/select.cljx +++ b/src/hickory/select.cljc @@ -5,7 +5,7 @@ (:require [clojure.zip :as zip] [clojure.string :as string] [hickory.zip :as hzip]) - #+clj (:import clojure.lang.IFn) + #?(:clj (:import clojure.lang.IFn)) (:refer-clojure :exclude [and or not class])) ;; @@ -660,4 +660,3 @@ zip/right #(nil? %)) hzip-loc))))) - diff --git a/src/hickory/utils.cljx b/src/hickory/utils.cljc similarity index 81% rename from src/hickory/utils.cljx rename to src/hickory/utils.cljc index 4dbd2ea..b4c677c 100644 --- a/src/hickory/utils.cljx +++ b/src/hickory/utils.cljc @@ -1,8 +1,8 @@ (ns hickory.utils "Miscellaneous utilities used internally." - #+clj (:require [quoin.text :as qt]) + #?(:clj (:require [quoin.text :as qt])) (:require [clojure.string :as string] - #+cljs [goog.string :as gstring])) + #?(:cljs [goog.string :as gstring]))) ;; ;; Data @@ -23,13 +23,13 @@ (defn html-escape [s] - #+clj (qt/html-escape s) - #+cljs (gstring/htmlEscape s)) + #?(:clj (qt/html-escape s)) + #?(:cljs (gstring/htmlEscape s))) (defn starts-with [^String s ^String prefix] - #+clj (.startsWith s prefix) - #+cljs (goog.string.startsWith s prefix)) + #?(:clj (.startsWith s prefix)) + #?(:cljs (goog.string.startsWith s prefix))) (defn lower-case-keyword "Converts its string argument into a lowercase keyword." diff --git a/src/hickory/zip.cljx b/src/hickory/zip.cljc similarity index 100% rename from src/hickory/zip.cljx rename to src/hickory/zip.cljc From 6d1a7dcf30de89f102cac1b0bbac44d7119df3a3 Mon Sep 17 00:00:00 2001 From: Edward Knyshov Date: Tue, 17 Nov 2015 03:11:12 +0300 Subject: [PATCH 2/3] add escape parameter to as-hiccup to fix #25 --- .gitignore | 1 + README.md | 60 +++++++++++++++++++++---------------------- src/hickory/core.clj | 28 +++++++++++--------- src/hickory/core.cljs | 56 +++++++++++++++++++++------------------- 4 files changed, 77 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index 8d812d9..0fbf270 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ pom.xml .lein-repl-history /.nrepl-port /.cljs_rhino_repl/ +/out/ diff --git a/README.md b/README.md index 00caee6..1a0f1d6 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ parsing functions, `parse` and `parse-fragment`. Both take a string containing HTML and return the parser objects representing the document. (It happens that these parser objects are Jsoup Documents and Nodes, but I do not consider this to be an aspect worth preserving -if a change in parser should become necessary). +if a change in parser should become necessary). The first function, `parse` expects an entire HTML document, and parses it using an HTML5 parser ([Jsoup](http://jsoup.org) on Clojure and @@ -35,7 +35,7 @@ simply give you the list of nodes that it parsed. These parsed objects can be turned into either Hiccup vector trees or Hickory DOM maps using the functions `as-hiccup` or `as-hickory`. -Here's a usage example. +Here's a usage example. ```clojure user=> (use 'hickory.core) @@ -48,10 +48,10 @@ user=> (as-hickory parsed-doc) {:type :document, :content [{:type :element, :attrs nil, :tag :html, :content [{:type :element, :attrs nil, :tag :head, :content nil} {:type :element, :attrs nil, :tag :body, :content [{:type :element, :attrs {:href "foo"}, :tag :a, :content ["foo"]}]}]}]} user=> (def parsed-frag (parse-fragment "foo bar")) #'user/parsed-frag -user=> (as-hiccup parsed-frag) +user=> (as-hiccup parsed-frag false) IllegalArgumentException No implementation of method: :as-hiccup of protocol: #'hickory.core/HiccupRepresentable found for class: clojure.lang.PersistentVector clojure.core/-cache-protocol-fn (core_deftype.clj:495) -user=> (map as-hiccup parsed-frag) +user=> (map #(as-hiccup % false) parsed-frag) ([:a {:href "foo"} "foo"] " " [:a {:href "bar"} "bar"]) user=> (map as-hickory parsed-frag) ({:type :element, :attrs {:href "foo"}, :tag :a, :content ["foo"]} " " {:type :element, :attrs {:href "bar"}, :tag :a, :content ["bar"]}) @@ -75,25 +75,25 @@ user=> (use 'hickory.zip) nil user=> (require '[clojure.zip :as zip]) nil -user=> (-> (hiccup-zip (as-hiccup (parse "bar
"))) zip/node) +user=> (-> (hiccup-zip (as-hiccup (parse "bar
") false)) zip/node) ([:html {} [:head {}] [:body {} [:a {:href "foo"} "bar" [:br {}]]]]) -user=> (-> (hiccup-zip (as-hiccup (parse "bar
"))) zip/next zip/node) +user=> (-> (hiccup-zip (as-hiccup (parse "bar
") false)) zip/next zip/node) [:html {} [:head {}] [:body {} [:a {:href "foo"} "bar" [:br {}]]]] -user=> (-> (hiccup-zip (as-hiccup (parse "bar
"))) zip/next zip/next zip/node) +user=> (-> (hiccup-zip (as-hiccup (parse "bar
") false)) zip/next zip/next zip/node) [:head {}] -user=> (-> (hiccup-zip (as-hiccup (parse "bar
"))) - zip/next zip/next - (zip/replace [:head {:id "a"}]) +user=> (-> (hiccup-zip (as-hiccup (parse "bar
") false)) + zip/next zip/next + (zip/replace [:head {:id "a"}]) zip/node) [:head {:id "a"}] -user=> (-> (hiccup-zip (as-hiccup (parse "bar
"))) - zip/next zip/next - (zip/replace [:head {:id "a"}]) +user=> (-> (hiccup-zip (as-hiccup (parse "bar
") false)) + zip/next zip/next + (zip/replace [:head {:id "a"}]) zip/root) ([:html {} [:head {:id "a"}] [:body {} [:a {:href "foo"} "bar" [:br {}]]]]) -user=> (-> (hickory-zip (as-hickory (parse "bar
"))) - zip/next zip/next - (zip/replace {:type :element :tag :head :attrs {:id "a"} :content nil}) +user=> (-> (hickory-zip (as-hickory (parse "bar
"))) + zip/next zip/next + (zip/replace {:type :element :tag :head :attrs {:id "a"} :content nil}) zip/root) {:type :document, :content [{:type :element, :attrs nil, :tag :html, :content [{:content nil, :type :element, :attrs {:id "a"}, :tag :head} {:type :element, :attrs nil, :tag :body, :content [{:type :element, :attrs {:href "foo"}, :tag :a, :content ["bar" {:type :element, :attrs nil, :tag :br, :content nil}]}]}]}]} user=> (hickory-to-html *1) @@ -139,11 +139,11 @@ nil user=> (def site-htree (-> (client/get "http://formula1.com/default.html") :body parse as-hickory)) #'user/site-htree user=> (-> (s/select (s/child (s/class "subCalender") ; sic - (s/tag :div) - (s/id :raceDates) + (s/tag :div) + (s/id :raceDates) s/first-child - (s/tag :b)) - site-htree) + (s/tag :b)) + site-htree) first :content first string/trim) "10, 11, 12 May 2013" ``` @@ -182,19 +182,19 @@ There are also selector combinators, which take as argument some number of other - `child`: Takes any number of selectors as arguments and returns a selector that returns true when the zipper location given as the argument is at the end of a chain of direct child relationships specified by the selectors given as arguments. - `descendant`: Takes any number of selectors as arguments and returns a selector that returns true when the zipper location given as the argument is at the end of a chain of descendant relationships specified by the selectors given as arguments. -We can illustrate the selector combinators by continuing the Formula 1 example above. We suspect, to our dismay, that Sebastian Vettel is leading the championship for the fourth year in a row. +We can illustrate the selector combinators by continuing the Formula 1 example above. We suspect, to our dismay, that Sebastian Vettel is leading the championship for the fourth year in a row. ```clojure -user=> (-> (s/select (s/descendant (s/class "subModule") - (s/class "standings") - (s/and (s/tag :tr) - s/first-child) - (s/and (s/tag :td) - (s/nth-child 2)) - (s/tag :a)) - site-htree) +user=> (-> (s/select (s/descendant (s/class "subModule") + (s/class "standings") + (s/and (s/tag :tr) + s/first-child) + (s/and (s/tag :td) + (s/nth-child 2)) + (s/tag :a)) + site-htree) first :content first string/trim) -"Sebastian Vettel" +"Sebastian Vettel" ``` Our fears are confirmed, Sebastian Vettel is well on his way to a fourth consecutive championship. If you were to inspect the page by hand (as of around May 2013, at least), you would see that unlike the `child` selector we used in the example above, the `descendant` selector allows the argument selectors to skip stages in the tree; we've left out some elements in this descendant relationship. The first table row in the driver standings table is selected with the `and`, `tag` and `first-child` selectors, and then the second `td` element is chosen, which is the element that has the driver's name (the first table element has the driver's standing) inside an `A` element. All of this is dependent on the exact layout of the HTML in the site we are examining, of course, but it should give an idea of how you can combine selectors to reach into a specific node of an HTML document very easily. diff --git a/src/hickory/core.clj b/src/hickory/core.clj index d0f6f5a..2189d14 100644 --- a/src/hickory/core.clj +++ b/src/hickory/core.clj @@ -13,7 +13,7 @@ (defprotocol HiccupRepresentable "Objects that can be represented as Hiccup nodes implement this protocol in order to make the conversion." - (as-hiccup [this] + (as-hiccup [this escape] "Converts the node given into a hiccup-format data structure. The node must have an implementation of the HiccupRepresentable protocol; nodes created by parse or parse-fragment already do.")) @@ -39,20 +39,20 @@ (extend-protocol HiccupRepresentable Attribute ;; Note the attribute value is not html-escaped; see comment for Element. - (as-hiccup [this] [(utils/lower-case-keyword (.getKey this)) + (as-hiccup [this escape] [(utils/lower-case-keyword (.getKey this)) (.getValue this)]) Attributes - (as-hiccup [this] (into {} (map as-hiccup this))) + (as-hiccup [this escape] (into {} (map #(as-hiccup % escape) this))) Comment - (as-hiccup [this] (str "")) + (as-hiccup [this escape] (str "")) DataNode - (as-hiccup [this] (str this)) + (as-hiccup [this escape] (str this)) Document - (as-hiccup [this] (map as-hiccup (.childNodes this))) + (as-hiccup [this escape] (map #(as-hiccup % escape) (.childNodes this))) DocumentType - (as-hiccup [this] (str this)) + (as-hiccup [this escape] (str this)) Element - (as-hiccup [this] + (as-hiccup [this escape] ;; There is an issue with the hiccup format, which is that it ;; can't quite cover all the pieces of HTML, so anything it ;; doesn't cover is thrown into a string containing the raw @@ -67,15 +67,19 @@ ;; unescapable nodes. (let [tag (utils/lower-case-keyword (.tagName this))] (into [] (concat [tag - (as-hiccup (.attributes this))] + (as-hiccup (.attributes this) escape)] (if (utils/unescapable-content tag) (map str (.childNodes this)) - (map as-hiccup (.childNodes this))))))) + (map #(as-hiccup % escape) (.childNodes this))))))) TextNode ;; See comment for Element re: html escaping. - (as-hiccup [this] (utils/html-escape (.getWholeText this))) + (as-hiccup [this escape] + (let [unescaped (.getWholeText this)] + (if escape + (utils/html-escape unescaped) + unescaped))) XmlDeclaration - (as-hiccup [this] (str this))) + (as-hiccup [this escape] (str this))) (extend-protocol HickoryRepresentable Attribute diff --git a/src/hickory/core.cljs b/src/hickory/core.cljs index 98293a9..f32eb24 100644 --- a/src/hickory/core.cljs +++ b/src/hickory/core.cljs @@ -10,7 +10,7 @@ (defprotocol HiccupRepresentable "Objects that can be represented as Hiccup nodes implement this protocol in order to make the conversion." - (as-hiccup [this] + (as-hiccup [this escape] "Converts the node given into a hiccup-format data structure. The node must have an implementation of the HiccupRepresentable protocol; nodes created by parse or parse-fragment already do.")) @@ -68,31 +68,35 @@ (extend-protocol HiccupRepresentable object - (as-hiccup [this] (condp = (aget this "nodeType") - Attribute [(utils/lower-case-keyword (aget this "name")) - (aget this "value")] - Comment (str "") - Document (map as-hiccup (aget this "childNodes")) - DocumentType (format-doctype this) - ;; There is an issue with the hiccup format, which is that it - ;; can't quite cover all the pieces of HTML, so anything it - ;; doesn't cover is thrown into a string containing the raw - ;; HTML. This presents a problem because it is then never the case - ;; that a string in a hiccup form should be html-escaped (except - ;; in an attribute value) when rendering; it should already have - ;; any escaping. Since the HTML parser quite properly un-escapes - ;; HTML where it should, we have to go back and un-un-escape it - ;; wherever text would have been un-escaped. We do this by - ;; html-escaping the parsed contents of text nodes, and not - ;; html-escaping comments, data-nodes, and the contents of - ;; unescapable nodes. - Element (let [tag (utils/lower-case-keyword (aget this "tagName"))] - (into [] (concat [tag - (into {} (map as-hiccup (aget this "attributes")))] - (if (utils/unescapable-content tag) - (map #(aget % "wholeText") (aget this "childNodes")) - (map as-hiccup (aget this "childNodes")))))) - Text (utils/html-escape (aget this "wholeText"))))) + (as-hiccup [this escape] + (condp = (aget this "nodeType") + Attribute [(utils/lower-case-keyword (aget this "name")) + (aget this "value")] + Comment (str "") + Document (map #(as-hiccup % escape) (aget this "childNodes")) + DocumentType (format-doctype this) + ;; There is an issue with the hiccup format, which is that it + ;; can't quite cover all the pieces of HTML, so anything it + ;; doesn't cover is thrown into a string containing the raw + ;; HTML. This presents a problem because it is then never the case + ;; that a string in a hiccup form should be html-escaped (except + ;; in an attribute value) when rendering; it should already have + ;; any escaping. Since the HTML parser quite properly un-escapes + ;; HTML where it should, we have to go back and un-un-escape it + ;; wherever text would have been un-escaped. We do this by + ;; html-escaping the parsed contents of text nodes, and not + ;; html-escaping comments, data-nodes, and the contents of + ;; unescapable nodes. + Element (let [tag (utils/lower-case-keyword (aget this "tagName"))] + (into [] (concat [tag + (into {} (map #(as-hiccup % escape) (aget this "attributes")))] + (if (utils/unescapable-content tag) + (map #(aget % "wholeText") (aget this "childNodes")) + (map #(as-hiccup % escape) (aget this "childNodes")))))) + Text (let [unescaped (aget this "wholeText")] + (if escape + (utils/html-escape unescaped) + unescaped))))) (extend-protocol HickoryRepresentable object From 2094e5c8ad1e83890d74e6c7dca8c31871c6cf8e Mon Sep 17 00:00:00 2001 From: Edward Knyshov Date: Tue, 17 Nov 2015 03:28:48 +0300 Subject: [PATCH 3/3] use modern clojure script version, fix tests --- project.clj | 2 +- .../test/{convert.cljx => convert.cljc} | 31 ++++---- test/hickory/test/{core.cljx => core.cljc} | 16 ++-- .../{hiccup_utils.cljx => hiccup_utils.cljc} | 75 +++++++++---------- .../hickory/test/{render.cljx => render.cljc} | 37 ++++----- .../hickory/test/{select.cljx => select.cljc} | 6 +- test/hickory/test/{zip.cljx => zip.cljc} | 16 ++-- 7 files changed, 91 insertions(+), 92 deletions(-) rename test/hickory/test/{convert.cljx => convert.cljc} (68%) rename test/hickory/test/{core.cljx => core.cljc} (93%) rename test/hickory/test/{hiccup_utils.cljx => hiccup_utils.cljc} (54%) rename test/hickory/test/{render.cljx => render.cljc} (73%) rename test/hickory/test/{select.cljx => select.cljc} (99%) rename test/hickory/test/{zip.cljx => zip.cljc} (87%) diff --git a/project.clj b/project.clj index b5e6841..b323d9d 100644 --- a/project.clj +++ b/project.clj @@ -10,7 +10,7 @@ [org.jsoup/jsoup "1.7.1"]] :plugins [[codox "0.6.4"]] :profiles {:dev - {:dependencies [[org.clojure/clojurescript "1.7.170"]] + {:dependencies [[org.clojure/clojurescript "1.7.145"]] :plugins [[lein-cljsbuild "1.1.1"] [com.cemerick/clojurescript.test "0.3.3"]]}} :codox {:sources ["src" "target/generated-src"] diff --git a/test/hickory/test/convert.cljx b/test/hickory/test/convert.cljc similarity index 68% rename from test/hickory/test/convert.cljx rename to test/hickory/test/convert.cljc index 34f412a..52ce60f 100644 --- a/test/hickory/test/convert.cljx +++ b/test/hickory/test/convert.cljc @@ -1,41 +1,40 @@ (ns hickory.test.convert - #+clj (:use clojure.test) + #?(:clj (:use clojure.test)) (:require [hickory.convert :refer [hiccup-fragment-to-hickory hiccup-to-hickory hickory-to-hiccup]] [hickory.core :refer [as-hickory as-hiccup parse parse-fragment]] - #+cljs [cemerick.cljs.test :as t]) - #+cljs (:require-macros [cemerick.cljs.test :refer (is deftest)])) + #?(:cljs [cemerick.cljs.test :as t])) + #?(:cljs (:require-macros [cemerick.cljs.test :refer (is deftest)]))) (deftest hiccup-to-hickory-test (is (= (as-hickory (parse "Hi.")) - (hiccup-to-hickory (as-hiccup (parse "Hi."))))) + (hiccup-to-hickory (as-hiccup (parse "Hi.") true)))) (is (= (as-hickory (parse "OuterInner.")) - (hiccup-to-hickory (as-hiccup (parse "OuterInner."))))) + (hiccup-to-hickory (as-hiccup (parse "OuterInner.") true)))) (is (= (as-hickory (parse "Hi")) - (hiccup-to-hickory (as-hiccup (parse "Hi"))))) + (hiccup-to-hickory (as-hiccup (parse "Hi") true)))) (is (= (as-hickory (parse "")) - (hiccup-to-hickory (as-hiccup (parse "")))))) + (hiccup-to-hickory (as-hiccup (parse "") true))))) (deftest hiccup-fragment-to-hickory-test (is (= (map as-hickory (parse-fragment "")) - (hiccup-fragment-to-hickory (map as-hiccup (parse-fragment ""))))) + (hiccup-fragment-to-hickory (map #(as-hiccup % true) (parse-fragment ""))))) (let [src "It's an a."] (is (= (map as-hickory (parse-fragment src)) - (hiccup-fragment-to-hickory (map as-hiccup (parse-fragment src))))))) + (hiccup-fragment-to-hickory (map #(as-hiccup % true) (parse-fragment src))))))) (deftest hickory-to-hiccup-test - (is (= (as-hiccup (parse "Hi.")) + (is (= (as-hiccup (parse "Hi.") true) (hickory-to-hiccup (as-hickory (parse "Hi."))))) - (is (= (as-hiccup (parse "OuterInner.")) + (is (= (as-hiccup (parse "OuterInner.") true) (hickory-to-hiccup (as-hickory (parse "OuterInner."))))) - (is (= (as-hiccup (parse "Hi")) + (is (= (as-hiccup (parse "Hi") true) (hickory-to-hiccup (as-hickory (parse "Hi"))))) - (is (= (as-hiccup (parse "")) + (is (= (as-hiccup (parse "") true) (hickory-to-hiccup (as-hickory (parse ""))))) ;; Fragments - (is (= (map as-hiccup (parse-fragment "")) + (is (= (map #(as-hiccup % true) (parse-fragment "")) (map hickory-to-hiccup (map as-hickory (parse-fragment ""))))) (let [src "It's an a."] - (is (= (map as-hiccup (parse-fragment src)) + (is (= (map #(as-hiccup % true) (parse-fragment src)) (map hickory-to-hiccup (map as-hickory (parse-fragment src))))))) - diff --git a/test/hickory/test/core.cljx b/test/hickory/test/core.cljc similarity index 93% rename from test/hickory/test/core.cljx rename to test/hickory/test/core.cljc index d00ab3b..f6e0bb8 100644 --- a/test/hickory/test/core.cljx +++ b/test/hickory/test/core.cljc @@ -1,8 +1,8 @@ (ns hickory.test.core - #+clj (:use clojure.test) + #?(:clj (:use clojure.test)) (:require [hickory.core :refer [as-hickory as-hiccup parse parse-fragment]] - #+cljs [cemerick.cljs.test :as t]) - #+cljs (:require-macros [cemerick.cljs.test :refer (is deftest)])) + #?(:cljs [cemerick.cljs.test :as t])) + #?(:cljs (:require-macros [cemerick.cljs.test :refer (is deftest)]))) ;; This document tests: doctypes, white space text nodes, attributes, ;; and cdata nodes. @@ -14,7 +14,7 @@ [:a {:href "foo"} "foo"] " " [:a {:id "so", :href "bar"} "bar"] [:script {:src "blah.js"} "alert(\"hi\");"]]]] - (as-hiccup (parse "foo bar")))) + (as-hiccup (parse "foo bar") true))) (is (= {:type :document, :content [{:type :document-type, :attrs {:name "html", :publicid "", :systemid ""}} @@ -54,7 +54,7 @@ [:a {:href "foo"} "foo"] " " [:a {:id "so", :href "bar"} "bar"] [:script {:src "blah.js"} "alert(\"hi\");"]]]] - (as-hiccup (parse "foo bar")))) + (as-hiccup (parse "foo bar") true))) (is (= {:type :document, :content [{:type :document-type, :attrs {:name "html", :publicid "", :systemid ""}} @@ -90,7 +90,7 @@ (deftest basic-document-fragment (is (= [[:a {:href "foo"} "foo"] " " [:a {:href "bar"} "bar"]] - (map as-hiccup + (map #(as-hiccup % true) (parse-fragment "foo bar")))) (is (= [{:type :element, :attrs {:href "foo"}, @@ -109,10 +109,10 @@ ;; strings that aren't attribute values, so the hiccup representation will ;; have the string contents html-escaped. (is (= [[:html {} [:head {}] [:body {} [:p {} "ABC&\n\nDEF."]]]] - (as-hiccup (parse "

ABC&\n\nDEF.

")))) + (as-hiccup (parse "

ABC&\n\nDEF.

") true))) ;;
 tag preserves whitespace.
   (is (= [[:html {} [:head {}] [:body {} [:pre {} "ABC&\n\nDEF."]]]]
-         (as-hiccup (parse "
ABC&\n\nDEF.
")))) + (as-hiccup (parse "
ABC&\n\nDEF.
") true))) ;; Hickory versions - Note that the representation is different, and Hickory ;; format does not keep HTML escaped in its representation, as it can ;; figure out what to escape at render time. diff --git a/test/hickory/test/hiccup_utils.cljx b/test/hickory/test/hiccup_utils.cljc similarity index 54% rename from test/hickory/test/hiccup_utils.cljx rename to test/hickory/test/hiccup_utils.cljc index a7f8a10..c86a036 100644 --- a/test/hickory/test/hiccup_utils.cljx +++ b/test/hickory/test/hiccup_utils.cljc @@ -1,18 +1,18 @@ (ns hickory.test.hiccup-utils - #+clj (:use clojure.test) + #?(:clj (:use clojure.test)) (:require [hickory.hiccup-utils :refer [class-names id normalize-form tag-name tag-well-formed?]] - #+cljs [cemerick.cljs.test :as t]) - #+cljs (:require-macros [cemerick.cljs.test :refer (is deftest)])) + #?(:cljs [cemerick.cljs.test :as t])) + #?(:cljs (:require-macros [cemerick.cljs.test :refer (is deftest)]))) -#+clj -(deftest first-idx-test - (let [first-idx #'hickory.hiccup-utils/first-idx] - (is (= -1 (first-idx -1 -1))) - (is (= 2 (first-idx -1 2))) - (is (= 5 (first-idx 5 -1))) - (is (= 3 (first-idx 5 3))) - (is (= 3 (first-idx 3 5))))) +#?(:clj + (deftest first-idx-test + (let [first-idx #'hickory.hiccup-utils/first-idx] + (is (= -1 (first-idx -1 -1))) + (is (= 2 (first-idx -1 2))) + (is (= 5 (first-idx 5 -1))) + (is (= 3 (first-idx 5 3))) + (is (= 3 (first-idx 3 5)))))) (deftest tag-well-formed?-test (is (= true (tag-well-formed? :a))) @@ -51,33 +51,33 @@ (is (= "foo" (id :a#foo))) (is (= "foo" (id :a#foo.bar)))) -#+clj -(deftest expand-content-seqs-test - (let [expand-content-seqs #'hickory.hiccup-utils/expand-content-seqs] - (is (= [1 2 3] (expand-content-seqs [1 2 3]))) - (is (= [1 2 [3]] (expand-content-seqs [1 '(2 [3])]))) - ;; Example from docstring. - (is (= [1 2 3 2 4 6 [5]] - (expand-content-seqs [1 '(2 3) (for [x [1 2 3]] (* x 2)) [5]]))))) +#?(:clj + (deftest expand-content-seqs-test + (let [expand-content-seqs #'hickory.hiccup-utils/expand-content-seqs] + (is (= [1 2 3] (expand-content-seqs [1 2 3]))) + (is (= [1 2 [3]] (expand-content-seqs [1 '(2 [3])]))) + ;; Example from docstring. + (is (= [1 2 3 2 4 6 [5]] + (expand-content-seqs [1 '(2 3) (for [x [1 2 3]] (* x 2)) [5]])))))) -#+clj -(deftest normalize-element-test - (let [normalize-element #'hickory.hiccup-utils/normalize-element] - (is (= [:a {:id nil :class nil} "Hi"] (normalize-element [:a "Hi"]))) - (is (= [:a {:id "foo" :class nil} "Hi"] - (normalize-element [:A#foo "Hi"]))) - (is (= [:a {:id nil :class "foo"} "Hi"] - (normalize-element [:a.foo "Hi"]))) - (is (= [:a {:id "foo" :class "bar"} "Hi" "There"] - (normalize-element [:a#foo.bar "Hi" "There"]))) - (is (= [:a {:id "foo" :class "bar"} "Hi"] - (normalize-element [:a.bar {:id "foo"} "Hi"]))) - (is (= [:a {:id "foo" :class "bar"}] - (normalize-element [:A#bip {:id "foo" :class "bar"}]))) - (is (= [:a {:id "foo" :class "bar"}] - (normalize-element [:a#bip.baz {:id "foo" :class "bar"}]))) - (is (= [:a {:id nil :class "foo bar"}] - (normalize-element [:a.foo.bar]))))) +#?(:clj + (deftest normalize-element-test + (let [normalize-element #'hickory.hiccup-utils/normalize-element] + (is (= [:a {:id nil :class nil} "Hi"] (normalize-element [:a "Hi"]))) + (is (= [:a {:id "foo" :class nil} "Hi"] + (normalize-element [:A#foo "Hi"]))) + (is (= [:a {:id nil :class "foo"} "Hi"] + (normalize-element [:a.foo "Hi"]))) + (is (= [:a {:id "foo" :class "bar"} "Hi" "There"] + (normalize-element [:a#foo.bar "Hi" "There"]))) + (is (= [:a {:id "foo" :class "bar"} "Hi"] + (normalize-element [:a.bar {:id "foo"} "Hi"]))) + (is (= [:a {:id "foo" :class "bar"}] + (normalize-element [:A#bip {:id "foo" :class "bar"}]))) + (is (= [:a {:id "foo" :class "bar"}] + (normalize-element [:a#bip.baz {:id "foo" :class "bar"}]))) + (is (= [:a {:id nil :class "foo bar"}] + (normalize-element [:a.foo.bar])))))) (deftest normalize-form-test (is (= [:a {:id nil :class nil}] (normalize-form [:A]))) @@ -94,4 +94,3 @@ (is (= [:a {:id nil :class nil} [:b {:id nil :class nil} "foo" [:i {:id nil :class nil} "bar"]]] (normalize-form [:a [:b "foo" [:i "bar"]]])))) - diff --git a/test/hickory/test/render.cljx b/test/hickory/test/render.cljc similarity index 73% rename from test/hickory/test/render.cljx rename to test/hickory/test/render.cljc index e397aee..9d33d06 100644 --- a/test/hickory/test/render.cljx +++ b/test/hickory/test/render.cljc @@ -1,10 +1,10 @@ (ns hickory.test.render - #+clj (:use clojure.test) + #?(:clj (:use clojure.test)) (:require [hickory.core :refer [as-hiccup as-hickory parse parse-fragment]] [hickory.render :refer [hiccup-to-html hickory-to-html]] - #+cljs [cemerick.cljs.test :as t]) - #+cljs (:require-macros [cemerick.cljs.test :refer (is deftest)]) - #+clj (:import clojure.lang.ExceptionInfo)) + #?(:cljs [cemerick.cljs.test :as t])) + #?(:cljs (:require-macros [cemerick.cljs.test :refer (is deftest)])) + #?(:clj (:import clojure.lang.ExceptionInfo))) ;; ;; Hickory to HTML ;; @@ -41,19 +41,19 @@ (hickory-to-html (as-hickory (parse ""))))) ;; Apparently Chrome will parse this doctype as plain html5, so we can't ;; do a roundtrip test in cljs. - #+clj (is (= "" - (hickory-to-html (as-hickory (parse "")))))) - + #?(:clj (is (= "" + (hickory-to-html (as-hickory (parse ""))))))) + (deftest error-handling-test (let [data {:type :foo :tag :a :attrs {:foo "bar"}}] (is (thrown-with-msg? ExceptionInfo #"^Not a valid node: nil" (hickory-to-html nil))) - (is (thrown-with-msg? ExceptionInfo #+clj #"^Not a valid node: \{:type :foo, :attrs \{:foo \"bar\"\}, :tag :a\}" #+cljs #"^Not a valid node: \{:type :foo, :tag :a\, :attrs \{:foo \"bar\"\}}" + (is (thrown-with-msg? ExceptionInfo #?(:clj #"^Not a valid node: \{:type :foo, :attrs \{:foo \"bar\"\}, :tag :a\}") #?(:cljs #"^Not a valid node: \{:type :foo, :tag :a\, :attrs \{:foo \"bar\"\}}") (hickory-to-html data))) - (is (= data + (is (= data (try (hickory-to-html data) - (catch #+clj Exception #+cljs js/Error e (:dom (ex-data e)))))))) + (catch #?(:clj Exception) #?(:cljs js/Error) e (:dom (ex-data e)))))))) ;; ;; Hiccup to HTML @@ -61,23 +61,24 @@ (deftest hiccup-to-html-test (is (= "

hi

" - (hiccup-to-html (as-hiccup (parse "

hi"))))) + (hiccup-to-html (as-hiccup (parse "

hi") true)))) ;; Make sure void elements don't have closing tags. (is (= "Hi
There" - (hiccup-to-html (as-hiccup (parse "Hi
There"))))) + (hiccup-to-html (as-hiccup (parse "Hi
There") true)))) ;; Make sure text is properly escaped. (is (= "<html>" - (hiccup-to-html [(as-hiccup (first (parse-fragment "<html>")))]))) + (hiccup-to-html [(as-hiccup (first (parse-fragment "<html>")) true)]))) ;; Make sure the contents of script/style tags do not get html escaped. (is (= "" (hiccup-to-html [(as-hiccup - (first (parse-fragment "")))]))) + (first (parse-fragment "")) + true)]))) ;; Make sure attribute contents are html-escaped. (is (= "" - (hiccup-to-html [(as-hiccup (first (parse-fragment "")))])))) + (hiccup-to-html [(as-hiccup (first (parse-fragment "")) true)])))) (deftest hiccup-doctypes-test (is (= "" - (hiccup-to-html (as-hiccup (parse ""))))) - #+clj (is (= "" - (hiccup-to-html (as-hiccup (parse "")))))) + (hiccup-to-html (as-hiccup (parse "") true)))) + #?(:clj (is (= "" + (hiccup-to-html (as-hiccup (parse "") true)))))) diff --git a/test/hickory/test/select.cljx b/test/hickory/test/select.cljc similarity index 99% rename from test/hickory/test/select.cljx rename to test/hickory/test/select.cljc index fc926f0..0d7b41a 100644 --- a/test/hickory/test/select.cljx +++ b/test/hickory/test/select.cljc @@ -1,12 +1,12 @@ (ns hickory.test.select - #+clj (:use clojure.test) + #?(:clj (:use clojure.test)) (:require [hickory.core :as hickory] [hickory.select :as select] [hickory.utils :as utils] [hickory.zip :as hzip] [clojure.zip :as zip] - #+cljs [cemerick.cljs.test :as t]) - #+cljs (:require-macros [cemerick.cljs.test :refer (is deftest testing)])) + #?(:cljs [cemerick.cljs.test :as t])) + #?(:cljs (:require-macros [cemerick.cljs.test :refer (is deftest testing)]))) (def html1 " diff --git a/test/hickory/test/zip.cljx b/test/hickory/test/zip.cljc similarity index 87% rename from test/hickory/test/zip.cljx rename to test/hickory/test/zip.cljc index 6e3b539..b8c4569 100644 --- a/test/hickory/test/zip.cljx +++ b/test/hickory/test/zip.cljc @@ -1,10 +1,10 @@ (ns hickory.test.zip - #+clj (:use clojure.test) + #?(:clj (:use clojure.test)) (:require [clojure.zip :as zip] [hickory.core :refer [as-hiccup as-hickory parse]] [hickory.zip :refer [hickory-zip hiccup-zip]] - #+cljs [cemerick.cljs.test :as t]) - #+cljs (:require-macros [cemerick.cljs.test :refer (is deftest)])) + #?(:cljs [cemerick.cljs.test :as t])) + #?(:cljs (:require-macros [cemerick.cljs.test :refer (is deftest)]))) (deftest hickory-zipper (is (= {:type :document, @@ -70,16 +70,16 @@ (deftest hiccup-zipper (is (= '([:html {} [:head {}] [:body {} [:a {}]]]) - (zip/node (hiccup-zip (as-hiccup (parse "
")))))) + (zip/node (hiccup-zip (as-hiccup (parse "") true))))) (is (= [:html {} [:head {}] [:body {} [:a {}]]] - (-> (hiccup-zip (as-hiccup (parse ""))) + (-> (hiccup-zip (as-hiccup (parse "") true)) zip/next zip/node))) (is (= [:head {}] - (-> (hiccup-zip (as-hiccup (parse ""))) + (-> (hiccup-zip (as-hiccup (parse "") true)) zip/next zip/next zip/node))) (is (= [:body {} [:a {}]] - (-> (hiccup-zip (as-hiccup (parse ""))) + (-> (hiccup-zip (as-hiccup (parse "") true)) zip/next zip/next zip/next zip/node))) (is (= [:html {} [:head {}] [:body {} [:a {}]]] - (-> (hiccup-zip (as-hiccup (parse ""))) + (-> (hiccup-zip (as-hiccup (parse "") true)) zip/next zip/next zip/next zip/up zip/node))))