Add tests for markdown-clj and tools.namespace

See comment for why only one markdown test could be run.
Closes #1069 and #1064
This commit is contained in:
Gabriel Horner 2021-12-23 00:28:56 -05:00
parent 818f2a9931
commit c0588be686
12 changed files with 1186 additions and 2 deletions

View file

@ -104,7 +104,9 @@
listora/again {:mvn/version "1.0.0"}
org.clojure/tools.gitlibs {:mvn/version "2.4.172"}
environ/environ {:mvn/version "1.2.0"}
table/table {:git/url "https://github.com/cldwalker/table", :sha "55aef3d5fced682942af811bf5d642f79fb87688"}}
table/table {:git/url "https://github.com/cldwalker/table", :sha "55aef3d5fced682942af811bf5d642f79fb87688"}
markdown-clj/markdown-clj {:mvn/version "1.10.8"}
org.clojure/tools.namespace {:git/url "https://github.com/babashka/tools.namespace", :sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b"}}
:classpath-overrides {org.clojure/clojure nil
org.clojure/spec.alpha nil}}
:clj-nvd

View file

@ -56,6 +56,7 @@ The following libraries and projects are known to work with babashka.
- [contajners](#contajners)
- [dependency](#dependency)
- [specmonstah](#specmonstah)
- [markdown-clj](#markdown-clj)
- [Pods](#pods)
- [Projects](#projects-1)
- [babashka-test-action](#babashka-test-action)
@ -792,6 +793,10 @@ Represent dependency graphs as a directed acylic graph.
Write concise, maintainable test fixtures with clojure.spec.alpha.
### [markdown-clj](https://github.com/yogthos/markdown-clj)
Markdown parser that translates markdown to html.
## Pods
[Babashka pods](https://github.com/babashka/babashka.pods) are programs that can

View file

@ -16,4 +16,8 @@
org.clojars.askonomm/ruuter {:git-sha "78659212f95cac827efc816dfbdab8181c25fc3d", :git-url "https://github.com/askonomm/ruuter", :test-namespaces (ruuter.core-test)}
;; clojure.data.json-gen-test ommitted from test-namespaces b/c it hangs on stest/check
org.clojure/data.json {:git-sha "9f1c9ccf3fd3e5a39cfb7289d3d456e842ddf442", :git-url "https://github.com/clojure/data.json", :test-namespaces (clojure.data.json-test clojure.data.json-test-suite-test clojure.data.json-compat-0-1-test)}
io.replikativ/hasch {:git-sha "04d9c0bd34d86bad79502d8a6963eb2525a22b15", :git-url "https://github.com/replikativ/hasch", :test-namespaces (hasch.test)}}
io.replikativ/hasch {:git-sha "04d9c0bd34d86bad79502d8a6963eb2525a22b15", :git-url "https://github.com/replikativ/hasch", :test-namespaces (hasch.test)}
;; BB-TEST-PATCH: Removed markdown.md-file-test b/c tests hardcode path to test
;; files. Removed markdown.benchmark b/c it depends on criterium which isn't bb compatible
markdown-clj/markdown-clj {:git-sha "ac245d3049afa25a6d41fcb5ba5a268f52c610e4", :git-url "https://github.com/yogthos/markdown-clj", :test-namespaces (markdown.md-test)}
org.clojure/tools.namespace {:git-sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b", :git-url "https://github.com/babashka/tools.namespace", :test-namespaces (clojure.tools.namespace.test-helpers clojure.tools.namespace.dependency-test clojure.tools.namespace.find-test clojure.tools.namespace.move-test clojure.tools.namespace.parse-test clojure.tools.namespace.dir-test), :branch "babashka"}}

View file

@ -0,0 +1,315 @@
(ns clojure.tools.namespace.dependency-test
(:use clojure.test
clojure.tools.namespace.dependency))
;; building a graph like:
;;
;; :a
;; / |
;; :b |
;; \ |
;; :c
;; |
;; :d
;;
(def g1 (-> (graph)
(depend :b :a) ; "B depends on A"
(depend :c :b) ; "C depends on B"
(depend :c :a) ; "C depends on A"
(depend :d :c))) ; "D depends on C"
;; 'one 'five
;; | |
;; 'two |
;; / \ |
;; / \ |
;; / \ /
;; 'three 'four
;; | /
;; 'six /
;; | /
;; | /
;; | /
;; 'seven
;;
(def g2 (-> (graph)
(depend 'two 'one)
(depend 'three 'two)
(depend 'four 'two)
(depend 'four 'five)
(depend 'six 'three)
(depend 'seven 'six)
(depend 'seven 'four)))
;; :level0
;; / | | \
;; ----- | | -----
;; / | | \
;; :level1a :level1b :level1c :level1d
;; \ | | /
;; ----- | | -----
;; \ | | /
;; :level2
;; / | | \
;; ----- | | -----
;; / | | \
;; :level3a :level3b :level3c :level3d
;; \ | | /
;; ----- | | -----
;; \ | | /
;; :level4
;;
;; ... and so on in a repeating pattern like that, up to :level26
(def g3 (-> (graph)
(depend :level1a :level0)
(depend :level1b :level0)
(depend :level1c :level0)
(depend :level1d :level0)
(depend :level2 :level1a)
(depend :level2 :level1b)
(depend :level2 :level1c)
(depend :level2 :level1d)
(depend :level3a :level2)
(depend :level3b :level2)
(depend :level3c :level2)
(depend :level3d :level2)
(depend :level4 :level3a)
(depend :level4 :level3b)
(depend :level4 :level3c)
(depend :level4 :level3d)
(depend :level5a :level4)
(depend :level5b :level4)
(depend :level5c :level4)
(depend :level5d :level4)
(depend :level6 :level5a)
(depend :level6 :level5b)
(depend :level6 :level5c)
(depend :level6 :level5d)
(depend :level7a :level6)
(depend :level7b :level6)
(depend :level7c :level6)
(depend :level7d :level6)
(depend :level8 :level7a)
(depend :level8 :level7b)
(depend :level8 :level7c)
(depend :level8 :level7d)
(depend :level9a :level8)
(depend :level9b :level8)
(depend :level9c :level8)
(depend :level9d :level8)
(depend :level10 :level9a)
(depend :level10 :level9b)
(depend :level10 :level9c)
(depend :level10 :level9d)
(depend :level11a :level10)
(depend :level11b :level10)
(depend :level11c :level10)
(depend :level11d :level10)
(depend :level12 :level11a)
(depend :level12 :level11b)
(depend :level12 :level11c)
(depend :level12 :level11d)
(depend :level13a :level12)
(depend :level13b :level12)
(depend :level13c :level12)
(depend :level13d :level12)
(depend :level14 :level13a)
(depend :level14 :level13b)
(depend :level14 :level13c)
(depend :level14 :level13d)
(depend :level15a :level14)
(depend :level15b :level14)
(depend :level15c :level14)
(depend :level15d :level14)
(depend :level16 :level15a)
(depend :level16 :level15b)
(depend :level16 :level15c)
(depend :level16 :level15d)
(depend :level17a :level16)
(depend :level17b :level16)
(depend :level17c :level16)
(depend :level17d :level16)
(depend :level18 :level17a)
(depend :level18 :level17b)
(depend :level18 :level17c)
(depend :level18 :level17d)
(depend :level19a :level18)
(depend :level19b :level18)
(depend :level19c :level18)
(depend :level19d :level18)
(depend :level20 :level19a)
(depend :level20 :level19b)
(depend :level20 :level19c)
(depend :level20 :level19d)
(depend :level21a :level20)
(depend :level21b :level20)
(depend :level21c :level20)
(depend :level21d :level20)
(depend :level22 :level21a)
(depend :level22 :level21b)
(depend :level22 :level21c)
(depend :level22 :level21d)
(depend :level23a :level22)
(depend :level23b :level22)
(depend :level23c :level22)
(depend :level23d :level22)
(depend :level24 :level23a)
(depend :level24 :level23b)
(depend :level24 :level23c)
(depend :level24 :level23d)
(depend :level25a :level24)
(depend :level25b :level24)
(depend :level25c :level24)
(depend :level25d :level24)
(depend :level26 :level25a)
(depend :level26 :level25b)
(depend :level26 :level25c)
(depend :level26 :level25d)))
(deftest t-transitive-dependencies
(is (= #{:a :c :b}
(transitive-dependencies g1 :d)))
(is (= '#{two four six one five three}
(transitive-dependencies g2 'seven))))
(deftest t-transitive-dependencies-deep
(is (= #{:level0
:level1a :level1b :level1c :level1d
:level2
:level3a :level3b :level3c :level3d
:level4
:level5a :level5b :level5c :level5d
:level6
:level7a :level7b :level7c :level7d
:level8
:level9a :level9b :level9c :level9d
:level10
:level11a :level11b :level11c :level11d
:level12
:level13a :level13b :level13c :level13d
:level14
:level15a :level15b :level15c :level15d
:level16
:level17a :level17b :level17c :level17d
:level18
:level19a :level19b :level19c :level19d
:level20
:level21a :level21b :level21c :level21d
:level22
:level23a :level23b :level23c :level23d}
(transitive-dependencies g3 :level24)))
(is (= #{:level0
:level1a :level1b :level1c :level1d
:level2
:level3a :level3b :level3c :level3d
:level4
:level5a :level5b :level5c :level5d
:level6
:level7a :level7b :level7c :level7d
:level8
:level9a :level9b :level9c :level9d
:level10
:level11a :level11b :level11c :level11d
:level12
:level13a :level13b :level13c :level13d
:level14
:level15a :level15b :level15c :level15d
:level16
:level17a :level17b :level17c :level17d
:level18
:level19a :level19b :level19c :level19d
:level20
:level21a :level21b :level21c :level21d
:level22
:level23a :level23b :level23c :level23d
:level24
:level25a :level25b :level25c :level25d}
(transitive-dependencies g3 :level26))))
(deftest t-transitive-dependents
(is (= '#{four seven}
(transitive-dependents g2 'five)))
(is (= '#{four seven six three}
(transitive-dependents g2 'two))))
(defn- before?
"True if x comes before y in an ordered collection."
[coll x y]
(loop [[item & more] (seq coll)]
(cond (nil? item) true ; end of the seq
(= x item) true ; x comes first
(= y item) false
:else (recur more))))
(deftest t-before
(is (true? (before? [:a :b :c :d] :a :b)))
(is (true? (before? [:a :b :c :d] :b :c)))
(is (false? (before? [:a :b :c :d] :d :c)))
(is (false? (before? [:a :b :c :d] :c :a))))
(deftest t-topo-comparator-1
(let [sorted (sort (topo-comparator g1) [:d :a :b :foo])]
(are [x y] (before? sorted x y)
:a :b
:a :d
:a :foo
:b :d
:b :foo
:d :foo)))
(deftest t-topo-comparator-2
(let [sorted (sort (topo-comparator g2) '[three seven nine eight five])]
(are [x y] (before? sorted x y)
'three 'seven
'three 'eight
'three 'nine
'five 'eight
'five 'nine
'seven 'eight
'seven 'nine)))
(deftest t-topo-sort
(let [sorted (topo-sort g2)]
(are [x y] (before? sorted x y)
'one 'two
'one 'three
'one 'four
'one 'six
'one 'seven
'two 'three
'two 'four
'two 'six
'two 'seven
'three 'six
'three 'seven
'four 'seven
'five 'four
'five 'seven
'six 'seven)))
(deftest t-no-cycles
(is (thrown? Exception
(-> (graph)
(depend :a :b)
(depend :b :c)
(depend :c :a)))))
(deftest t-no-self-cycles
(is (thrown? Exception
(-> (graph)
(depend :a :b)
(depend :a :a)))))

View file

@ -0,0 +1,20 @@
(ns clojure.tools.namespace.dir-test
(:require [clojure.test :refer [deftest is]]
[clojure.tools.namespace.test-helpers :as help]
[clojure.tools.namespace.dir :as dir])
(:import
(java.io File)))
;; Only run this test on Java 1.7+, where java.nio.file.Files is available.
(when (try (Class/forName "java.nio.file.Files")
(catch ClassNotFoundException _ false))
(deftest t-scan-by-canonical-path
(let [dir (help/create-temp-dir "t-scan-by-canonical-path")
main-clj (help/create-source dir 'example.main :clj '[example.one])
one-cljc (help/create-source dir 'example.one :clj)
other-dir (help/create-temp-dir "t-scan-by-canonical-path-other")
link (File. other-dir "link")]
(java.nio.file.Files/createSymbolicLink (.toPath link) (.toPath dir)
(make-array java.nio.file.attribute.FileAttribute 0))
(is (= (::dir/files (dir/scan-dirs {} [dir]))
(::dir/files (dir/scan-dirs {} [link])))))))

View file

@ -0,0 +1,29 @@
(ns clojure.tools.namespace.find-test
(:require [clojure.test :refer [deftest is]]
[clojure.tools.namespace.test-helpers :as help]
[clojure.tools.namespace.find :as find])
(:import (java.io File)))
(deftest t-find-clj-and-cljc-files
"main.clj depends on one.cljc which depends on two.clj.
two.cljs also exists but should not be returned"
(let [dir (help/create-temp-dir "t-find-clj-and-cljc-files")
main-clj (help/create-source dir 'example.main :clj '[example.one])
one-cljc (help/create-source dir 'example.one :cljc '[example.two])
two-clj (help/create-source dir 'example.two :clj)
two-cljs (help/create-source dir 'example.two :cljs)]
(is (help/same-files?
[main-clj one-cljc two-clj]
(find/find-sources-in-dir dir)))))
(deftest t-find-cljs-and-cljc-files
"main.cljs depends on one.cljc which depends on two.cljs.
two.clj also exists but should not be returned"
(let [dir (help/create-temp-dir "t-find-cljs-and-cljc-files")
main-cljs (help/create-source dir 'example.main :cljs '[example.one])
one-cljc (help/create-source dir 'example.one :cljc '[example.two])
two-clj (help/create-source dir 'example.two :clj)
two-cljs (help/create-source dir 'example.two :cljs)]
(is (help/same-files?
[main-cljs one-cljc two-cljs]
(find/find-sources-in-dir dir find/cljs)))))

View file

@ -0,0 +1,52 @@
(ns clojure.tools.namespace.move-test
(:require [clojure.java.io :as io]
[clojure.test :refer [deftest is]]
[clojure.tools.namespace.move :refer [move-ns]]
[clojure.tools.namespace.test-helpers :as help])
(:import (java.io File)))
(defn- create-file-one [dir]
(help/create-source dir 'example.one :clj
'[example.two example.three]
'[(defn foo []
(example.a.four/foo))]))
(defn- create-file-two [dir]
(help/create-source dir 'example.two :clj
'[example.three example.a.four]))
(defn- create-file-three [dir]
(help/create-source dir 'example.three :clj
'[example.five]))
(defn- create-file-four [dir]
(help/create-source dir 'example.a.four :clj))
(deftest t-move-ns
(let [temp-dir (help/create-temp-dir "tools-namespace-t-move-ns")
src-dir (io/file temp-dir "src")
example-dir (io/file temp-dir "src" "example")
file-one (create-file-one src-dir)
file-two (create-file-two src-dir)
file-three (create-file-three src-dir)
old-file-four (create-file-four src-dir)
new-file-four (io/file example-dir "b" "four.clj")]
(let [file-three-last-modified (.lastModified file-three)]
(Thread/sleep 1500) ;; ensure file timestamps are different
(move-ns 'example.a.four 'example.b.four src-dir [src-dir])
(is (.exists new-file-four)
"new file should exist")
(is (not (.exists old-file-four))
"old file should not exist")
(is (not (.exists (.getParentFile old-file-four)))
"old empty directory should not exist")
(is (= file-three-last-modified (.lastModified file-three))
"unaffected file should not have been modified")
(is (not-any? #(.contains (slurp %) "example.a.four")
[file-one file-two file-three new-file-four]))
(is (every? #(.contains (slurp %) "example.b.four")
[file-one file-two new-file-four])))))

View file

@ -0,0 +1,210 @@
(ns clojure.tools.namespace.parse-test
(:use [clojure.test :only (deftest is)]
[clojure.tools.namespace.parse :only (deps-from-ns-decl
read-ns-decl)]))
(def ns-decl-prefix-list
'(ns com.example.one
(:require (com.example two
[three :as three]
[four :refer (a b)])
(com.example.sub [five :as five]
six))
(:use (com.example seven
[eight :as eight]
(nine :only (c d))
[ten]))))
;; Some people like to write prefix lists as vectors, not lists. The
;; use/require functions accept this form.
(def ns-decl-prefix-list-as-vector
'(ns com.example.one
(:require [com.example
two
[three :as three]
[four :refer (a b)]]
[com.example.sub
[five :as five]
six])
(:use [com.example
seven
[eight :as eight]
(nine :only (c d))
[ten]])))
(def ns-decl-prefix-list-clauses-as-vectors
"Sometimes people even write the clauses inside ns as vectors, which
clojure.core/ns allows. See TNS-21."
'(ns com.example.one
[:require [com.example
two
[three :as three]
[four :refer (a b)]]
[com.example.sub
[five :as five]
six]]
[:use [com.example
seven
[eight :as eight]
(nine :only (c d))
[ten]]]))
(def deps-from-prefix-list
'#{com.example.two
com.example.three
com.example.four
com.example.sub.five
com.example.sub.six
com.example.seven
com.example.eight
com.example.nine
com.example.ten})
(deftest t-prefix-list
(is (= deps-from-prefix-list
(deps-from-ns-decl ns-decl-prefix-list))))
(deftest t-prefix-list-as-vector
(is (= deps-from-prefix-list
(deps-from-ns-decl ns-decl-prefix-list-as-vector))))
(deftest t-prefix-list-clauses-as-vectors
(is (= deps-from-prefix-list
(deps-from-ns-decl ns-decl-prefix-list-clauses-as-vectors))))
(deftest t-no-deps-returns-empty-set
(is (= #{} (deps-from-ns-decl '(ns com.example.one)))))
(def multiple-ns-decls
'((ns one)
(ns two (:require one))
(ns three (:require [one :as o] [two :as t]))))
(def multiple-ns-decls-string
" (println \"Code before first ns\")
(ns one)
(println \"Some code\")
(defn hello-world [] \"Hello, World!\")
(ns two (:require one))
(println \"Some more code\")
(ns three (:require [one :as o] [two :as t]))")
(deftest t-read-multiple-ns-decls
(with-open [rdr (clojure.lang.LineNumberingPushbackReader.
(java.io.PushbackReader.
(java.io.StringReader. multiple-ns-decls-string)))]
(is (= multiple-ns-decls
(take-while identity (repeatedly #(read-ns-decl rdr)))))))
(def ns-docstring-example
"The example ns declaration used in the docstring of clojure.core/ns"
'(ns foo.bar
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql combinatorics))
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement))))
(def deps-from-ns-docstring-example
'#{clojure.contrib.sql
clojure.contrib.combinatorics
my.lib.this
my.lib.that})
(deftest t-ns-docstring-example
(is (= deps-from-ns-docstring-example
(deps-from-ns-decl ns-docstring-example))))
(def require-docstring-example
"The example ns declaration used in the docstring of
clojure.core/require"
'(ns (:require (clojure zip [set :as s]))))
(def deps-from-require-docstring-example
'#{clojure.zip
clojure.set})
(deftest t-require-docstring-example
(is (= deps-from-require-docstring-example
(deps-from-ns-decl require-docstring-example))))
(def multiple-clauses
"Example showing more than one :require or :use clause in one ns
declaration, which clojure.core/ns allows."
'(ns foo.bar
(:require com.example.one)
(:import java.io.File)
(:require (com.example two three))
(:use (com.example [four :only [x]]))
(:use (com.example (five :only [x])))))
(def deps-from-multiple-clauses
'#{com.example.one
com.example.two
com.example.three
com.example.four
com.example.five})
(deftest t-deps-from-multiple-clauses
(is (= deps-from-multiple-clauses
(deps-from-ns-decl multiple-clauses))))
(def clauses-without-keywords
"Example of require/use clauses with symbols instead of keywords,
which clojure.core/ns allows."
'(ns foo.bar
(require com.example.one)
(import java.io.File)
(use (com.example (prefixes (two :only [x])
three)))))
(def deps-from-clauses-without-keywords
'#{com.example.one
com.example.prefixes.two
com.example.prefixes.three})
(deftest t-clauses-without-keywords
(is (= deps-from-clauses-without-keywords
(deps-from-ns-decl clauses-without-keywords))))
(def reader-conditionals-string
"(ns com.examples.one
(:require #?(:clj clojure.string
:cljs goog.string)))")
(deftest t-reader-conditionals
;; TODO: the predicate wasn't added to bb yet, will come in version after 0.6.7
(when true #_(resolve 'clojure.core/reader-conditional?)
(let [actual (-> reader-conditionals-string
java.io.StringReader.
java.io.PushbackReader.
clojure.lang.LineNumberingPushbackReader.
read-ns-decl
deps-from-ns-decl)]
(is (= #{'clojure.string} actual)))))
(def ns-with-npm-dependency
"(ns com.examples.one
(:require [\"foobar\"] [baz]))")
(deftest npm-dependency
(let [actual (-> ns-with-npm-dependency
java.io.StringReader.
java.io.PushbackReader.
clojure.lang.LineNumberingPushbackReader.
read-ns-decl
deps-from-ns-decl)]
(is (= #{'baz} actual))))
(def ns-with-require-macros
"(ns com.examples.one
(:require-macros [foo :refer [bar]]))")
(deftest require-macros
(let [actual (-> ns-with-require-macros
java.io.StringReader.
java.io.PushbackReader.
clojure.lang.LineNumberingPushbackReader.
read-ns-decl
deps-from-ns-decl)]
(is (= #{'foo} actual))))

View file

@ -0,0 +1,82 @@
(ns clojure.tools.namespace.test-helpers
"Utilities to help with testing files and namespaces."
(:require [clojure.java.io :as io]
[clojure.string :as string])
(:import (java.io Closeable File Writer PrintWriter)))
(defn create-temp-dir
"Creates and returns a new temporary directory java.io.File."
[name]
(let [temp-file (File/createTempFile name nil)]
(.delete temp-file)
(.mkdirs temp-file)
(println "Temporary directory" (.getAbsolutePath temp-file))
temp-file))
(defn- write-contents
"Writes contents into writer. Strings are written as-is via println,
other types written as by prn."
[^Writer writer contents]
{:pre [(sequential? contents)]}
(binding [*out* (PrintWriter. writer)]
(doseq [content contents]
(if (string? content)
(println content)
(prn content))
(newline))))
(defn create-file
"Creates a file from a vector of path elements. Writes contents into
the file. Elements of contents may be data, written via prn, or
strings, written directly."
[path contents]
{:pre [(vector? path)]}
(let [^File file (apply io/file path)]
(when-let [parent (.getParentFile file)]
(.mkdirs parent))
(with-open [wtr (io/writer file)]
(write-contents wtr contents))
file))
(defn- sym->path
"Converts a symbol name into a vector of path parts, not including
file extension."
[symbol]
{:pre [(symbol? symbol)]
:post [(vector? %)]}
(-> (name symbol)
(string/replace \- \_)
(string/split #"\.")))
(defn- source-path
"Returns a vector of path components for namespace named sym,
with given file extension (keyword)."
[sym extension]
(let [path (sym->path sym)
basename (peek path)
filename (str basename \. (name extension))]
(conj (pop path) filename)))
(defn create-source
"Creates a file at the correct path under base-dir for a namespace
named sym, with file extension (keyword), containing a ns
declaration which :require's the dependencies (symbols). Optional
contents written after the ns declaration as by write-contents."
([base-dir sym extension]
(create-source base-dir sym extension nil nil))
([base-dir sym extension dependencies]
(create-source base-dir sym extension dependencies nil))
([base-dir sym extension dependencies contents]
(let [full-path (into [base-dir] (source-path sym extension))
ns-decl (if (seq dependencies)
(list 'ns sym (list* :require dependencies))
(list 'ns sym))]
(create-file full-path (into [ns-decl] contents)))))
(defn same-files?
"True if files-a and files-b contain the same canonical File's,
regardless of order."
[files-a files-b]
(= (sort (map #(.getCanonicalPath ^File %) files-a))
(sort (map #(.getCanonicalPath ^File %) files-b))))

View file

@ -0,0 +1,450 @@
(ns markdown.md-test
(:require #?(:cljs [goog.string])
[clojure.test :refer [deftest is]]
[markdown.core :as markdown]
[markdown.tables :as tables]))
(def entry-function
#?(:clj markdown/md-to-html-string
:cljs markdown/md->html))
(deftest heading1
(is (= "<h1>Ticket #123</h1>" (entry-function "# Ticket #123")))
(is (= "<h1>Foo</h1>" (entry-function " # Foo")))
(is (= "<h1>foo</h1>" (entry-function "#foo")))
(is (= "<h1>foo</h1>" (entry-function "foo\n===")))
(is (= "<h1>foo</h1>" (entry-function "#foo#")))
(is (= "<h1>foo</h1>" (entry-function "#foo#\n")))
(is (= "<h1>some header <code>with&#95;an&#95;underscore</code></h1>"
(entry-function "# some header `with_an_underscore`")))
(is (= "<ul><li>one</li></ul><h1>heading1</h1>"
(entry-function "* one\n\nheading1\n========\n"))))
(deftest heading2
(is (= "<h2>foo</h2>" (entry-function "##foo")))
(is (= "<h2>foo</h2>" (entry-function "foo\n---")))
(is (= "<h2>foo</h2>" (entry-function "##foo##")))
(is (= "<h2>foo</h2>" (entry-function "##foo##\n"))))
(deftest heading-with-complex-anchor
(is (=
"<h3 id=\"foo&#95;bar&#95;baz\">foo bar BAz</h3><p>some text</p>"
(entry-function "###foo bar BAz\nsome text" :heading-anchors true)))
(is (=
"<h3 id=\"foo&#95;bar&#95;baz\">foo bar BAz</h3><p>some text</p>"
(entry-function "###foo bar BAz##\nsome text" :heading-anchors true))))
(deftest br
(is (= "<p>foo<br /></p>" (entry-function "foo "))))
(deftest hr
(is (= "<hr/>" (entry-function "***")))
(is (= "<hr/>" (entry-function " * * * ")))
(is (= "<hr/>" (entry-function " *****")))
(is (= "<hr/>" (entry-function "- - - "))))
(deftest em
(is (= "<p><em>foo</em></p>" (entry-function "*foo*"))))
(deftest italics
(is (= "<p><i>foo</i></p>" (entry-function "_foo_"))))
(deftest strong
(is (= "<p><strong>foo</strong></p>" (entry-function "**foo**"))))
(deftest bold-italics
(is (= "<p><b><i>foo</i></b></p>" (entry-function "***foo***"))))
(deftest bold
(is (= "<p><b>foo</b></p>" (entry-function "__foo__"))))
(deftest strong-inside-em
(is (= "<p><em>foo<strong>bar</strong>baz</em></p>" (entry-function "*foo**bar**baz*"))))
(deftest bold-inside-a-list
(is (= "<ol><li>chickens.</li></ol><p> <strong>See more: <a href='http://cluck.cluck.com'>Cluck Cluck</a></strong> </p>"
(entry-function "1. chickens. \n\n **See more: [Cluck Cluck](http://cluck.cluck.com)** \n\n"))))
(deftest em-inside-strong
(is (= "<p><strong>foo<em>bar</em>baz</strong></p>" (entry-function "**foo*bar*baz**"))))
(deftest paragraph
(is (= "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore</p>"
(entry-function "\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore"))))
(deftest paragraph-multiline
(is (= "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore</p>"
(entry-function "\nLorem ipsum dolor\nsit amet, consectetur adipisicing elit,\nsed do eiusmod tempor incididunt ut labore"))))
(deftest paragraph-before-codeblock
(is (= "<p>foo</p><pre><code>bar\n</code></pre><p>baz</p>"
(entry-function "foo\n```\nbar\n```\nbaz")))
(is (= "<pre><code>foo \nbar</code></pre>" (entry-function "```\nfoo \nbar```")))
(is (= "<p><pre><code></code></pre></p>" (entry-function "```\n```")))
(is (= "<p><pre><code class=\"go\"></code></pre></p>" (entry-function "```go\n```")))
(is (= "<pre><code>&lt;html&gt;\n&lt;/html&gt;\n</code></pre>" (entry-function "```\n<html>\n</html>\n``` "))))
(deftest paragraph-after-codeblock
(is (= "<pre><code>foo\n</code></pre><p>bar baz</p>"
(entry-function "```\nfoo\n```\nbar\nbaz"))))
(deftest mulitple-paragraphs
(is (= "<p>foo bar baz</p><p>foo bar baz</p>"
(entry-function "\nfoo bar baz\n\n\nfoo bar baz"))))
(deftest ul
(is (= "<ul><li>foo</li><li>bar</li><li>baz</li></ul>"
(entry-function "* foo\n* bar\n* baz")))
(is (= "<ul><li>foo</li><li>bar</li><li>baz</li></ul>"
(entry-function "- foo\n- bar\n- baz")))
(is (= "<ul><li>foo</li><li>bar</li><li>baz</li></ul>"
(entry-function "+ foo\n+ bar\n+ baz"))))
(deftest list-in-a-codeblock
(is
(= "<pre><code class=\"yaml\">list:\n- 1\n- 2\n</code></pre>"
(entry-function "```yaml\nlist:\n- 1\n- 2\n```"))))
(deftest ul-followed-by-paragraph
(is (= "<ul><li>foo</li><li>bar</li><li>baz</li></ul><p>paragraph next line</p>"
(entry-function "* foo\n* bar\n* baz\n\nparagraph\nnext line"))))
(deftest ul-with-codeblock
(is (= "<ul><li>foo</li><li>bar<pre><code> &#40;defn foo &#91;&#93;\n bar&#41;\n </code></pre></li><li>baz</li><li>more text</li></ul>"
(entry-function
"\n* foo\n* bar\n ```\n (defn foo []\n bar)\n ```\n* baz\n* more text\n")))
(is (= "<ul><li>foo</li><li>bar<pre><code> &#40;defn foo &#91;&#93;\n bar&#41;\n </code></pre> text</li><li>baz</li><li>more text</li></ul>"
(entry-function
"\n* foo\n* bar\n ```\n (defn foo []\n bar)\n ```\n text\n* baz\n* more text\n"))))
(deftest ul-followed-by-multiline-paragraph
(is (= "<ul><li>foo</li><li>bar</li><li>baz</li></ul><p>paragraph</p>"
(entry-function "* foo\n* bar\n* baz\n\nparagraph"))))
(deftest ul-nested
(is (= "<ul><li>first item<ul><li>first sub-item<ul><li>second sub-item</li></ul></li><li>third sub-item</li></ul></li><li>second item<ul><li>first sub-item</li><li>second sub-item</li></ul></li><li>third item</li></ul>"
(entry-function "* first item\n * first sub-item\n * second sub-item\n * third sub-item\n* second item\n * first sub-item\n * second sub-item\n* third item")))
(is (= "<ul><li>first item<ul><li>first sub-item<ul><li>second sub-item</li></ul></li><li>third sub-item</li></ul></li><li>second item<ul><li>first sub-item</li><li>second sub-item</li></ul></li><li>third item</li></ul>"
(entry-function "* first item\n - first sub-item\n - second sub-item\n - third sub-item\n* second item\n + first sub-item\n + second sub-item\n* third item")))
(is (= "<ul><li>abc</li><li>def</li></ul>" (entry-function " * abc\n\n+ def"))))
(deftest ol
(is (= "<ol><li>Foo</li><li>Bar</li><li>Baz</li></ol>"
(entry-function "1. Foo\n2. Bar\n3. Baz"))))
(deftest ul-in-ol
(is (= "<ol><li>Bar<ol><li>Subbar<ul><li>foo</li><li>bar</li><li>baz</li></ul></li></ol></li><li>Baz</li></ol>"
(entry-function "1. Bar\n 2. Subbar\n * foo\n * bar\n * baz\n3. Baz"))))
(deftest ol-in-ul
(is (= "<ul><li>Foo<ol><li>Bar<ol><li>Subbar</li></ol></li></ol></li><li>Baz</li></ul>"
(entry-function "* Foo\n 1. Bar\n 1. Subbar\n* Baz")))
(is (= "<ul><li>Foo<ol><li>Bar</li></ol></li></ul>"
(entry-function "* Foo\n 1. Bar"))))
(deftest multilist
(is (=
"<ul><li>foo</li><li>bar<ul><li>baz<ol><li>foo</li><li>bar</li></ol></li><li>fuzz<ul><li>blah</li><li>blue</li></ul></li></ul></li><li>brass</li></ul>"
(entry-function
"* foo
* bar
* baz
1. foo
2. bar
* fuzz
* blah
* blue
* brass"))))
(deftest code
(is (= "<p>foo bar baz <code>x = y + z;</code> foo</p>"
(entry-function "foo bar baz `x = y + z;` foo")))
(is (= "<p>bar <code>foo --- -- bar</code> foo</p>"
(entry-function "bar `foo --- -- bar` foo")))
(is (= "<p><code>&lt;?xml version='1.0' encoding='UTF-8'?&gt;&lt;channel&gt;&lt;/channel&gt;</code></p>"
(entry-function "`<?xml version='1.0' encoding='UTF-8'?><channel></channel>`")))
(is (= "<p>foo bar baz <code>&#40;fn &#91;x &amp; xs&#93; &#40;str &quot;x:&quot; x&#41;&#41;</code> foo</p>"
(entry-function "foo bar baz `(fn [x & xs] (str \"x:\" x))` foo")))
(is (= "<pre><code>```\nfoo\n```</code></pre>"
(entry-function " ```\n foo\n ```"))))
(deftest multiline-code
(is (= "<pre><code>x = 5\ny = 6\nz = x + y</code></pre>"
(entry-function " x = 5\n y = 6\n z = x + y")))
(is (= "<pre><code>x = 5\ny = 6\nz = x + y\n&#40;fn &#91;x &amp; xs&#93; &#40;str &quot;x&quot;&#41;&#41;</code></pre>"
(entry-function " x = 5\n y = 6\n z = x + y\n (fn [x & xs] (str \"x\"))"))))
(deftest codeblock
(is (= "<pre><code>&#40;defn- write&#94; &#91;writer text&#93;\n &#40;doseq &#91;c text&#93;\n &#40;.write writer &#40;int c&#41;&#41;&#41;&#41;\n</code></pre>"
(entry-function "```\n(defn- write^ [writer text]\n (doseq [c text]\n (.write writer (int c))))\n```")))
(is (= "<pre><code>&#40;fn &#91;x &amp; xs&#93;\n &#40;str &quot;x&quot;&#41;&#41;\n</code></pre>"
(entry-function "```\n(fn [x & xs]\n (str \"x\"))\n```")))
(is (= "<pre><code>&#40;fn &#91;x &amp; xs&#93;\n &#40;str &quot;x&quot;&#41;&#41;\n</code></pre>"
(entry-function "```\n(fn [x & xs]\n (str \"x\"))\n```")))
(is (= "<pre><code class=\"clojure\">&#40;fn &#91;x &amp; xs&#93;\n &#40;str &quot;x&quot;&#41;&#41;\n</code></pre>"
(entry-function "```clojure\n(fn [x & xs]\n (str \"x\"))\n```")))
(is (= "<pre><code class=\"nohighlight\">------------\n============\n ------------\n ============\n</code></pre>"
(entry-function
"
```nohighlight
------------
============
------------
============
```
"))))
(deftest indented-codeblock
(is (= "<pre><code>foo</code></pre>"
(entry-function " foo")))
(is (= "<pre><code>foo</code></pre><p>bar</p>"
(entry-function " foo\n\nbar")))
(is (= "<pre><code>foo</code></pre>bar"
(entry-function " foo\nbar")))
(is (= "<p>baz foo</p><p>bar</p>"
(entry-function "baz\n foo\n\nbar")))
(is (= "<p><div class=\"grid-container\"> <div class=\"child1\"> <p>Element #1</p> </div> </div></p>"
(entry-function "<div class=\"grid-container\">\n <div class=\"child1\">\n <p>Element #1</p>\n </div>\n</div>"))))
(deftest strikethrough
(is (= "<p><del>foo</del></p>"
(entry-function "~~foo~~"))))
(deftest superscript
(is (= "<p>foo<sup>bar</sup> baz</p>"
(entry-function "foo^bar baz"))))
(deftest link
(is (= "<p><a href='http://underscores_are_fine.com'>underscores<i>are</i>fine</a></p>"
(entry-function "<a href='http://underscores_are_fine.com'>underscores_are_fine</a>")))
(is (= "<p><a href='http://github.com'>github</a></p>"
(entry-function "[github](http://github.com)")))
(is (= "<p><a href='http://github.com/~'>github</a></p>"
(entry-function "[github](http://github.com/~)")))
(is (= "<p><a href='http://github.com/^'>github</a></p>"
(entry-function "[github](http://github.com/^)")))
(is (= "<p><a href='http://github.com/*'>github</a></p>"
(entry-function "[github](http://github.com/*)")))
(is (= "<ul><li><a href='http://github.com/*'>github</a></li></ul>"
(entry-function "* [github](http://github.com/*)")))
(is (= "<ul><li>hi</li></ul><p><a href='https://see-here'>a link</a></p>"
(entry-function "* hi\n\n[a link](https://see-here)")))
(is (= "<p><a href='https://clojure.github.io/core.async/#clojure.core.async/>!'>>!</a></p>"
(entry-function "[>!](https://clojure.github.io/core.async/#clojure.core.async/>!)")))
(is (= "<p><a href='https://clojure.github.io/core.async/#clojure.core.async/<!'><!</a></p>"
(entry-function "[<!](https://clojure.github.io/core.async/#clojure.core.async/<!)"))))
(deftest styled-link
(is (= "<p><a href='http://github.com'><em>github</em></a></p>"
(entry-function "[*github*](http://github.com)")))
(is (= "<p><a href='http://github.com'><i>github</i></a></p>"
(entry-function "[_github_](http://github.com)")))
(is (= "<p><a href='http://github.com'><b>github</b></a></p>"
(entry-function "[__github__](http://github.com)")))
(is (= "<p><a href='http://github.com'><strong>github</strong></a></p>"
(entry-function "[**github**](http://github.com)")))
(is (= "<p><a href='http://github.com'><del>github</del></a></p>"
(entry-function "[~~github~~](http://github.com)"))))
(deftest img
(is (= "<p><img src=\"/path/to/img.jpg\" alt=\"Alt text\" /></p>"
(entry-function "![Alt text](/path/to/img.jpg)")))
(is (= "<p><img src=\"/path/to/_img_.jpg\" alt=\"Alt text\" title=\"Optional Title\" /></p>"
(entry-function "![Alt text](/path/to/_img_.jpg \"Optional Title\")"))))
(deftest img-link
(is (= "<p><a href='http://travis-ci.org/yogthos/markdown-clj'><img src=\"https://secure.travis-ci.org/yogthos/markdown-clj.png\" alt=\"Continuous Integration status\" /></a></p>"
(entry-function "[![Continuous Integration status](https://secure.travis-ci.org/yogthos/markdown-clj.png)](http://travis-ci.org/yogthos/markdown-clj)")))
(is (= "<p><img src=\"https://secure.travis-ci.org/yogthos/markdown-clj.png\" alt=\"\" /></p>"
(entry-function "![](https://secure.travis-ci.org/yogthos/markdown-clj.png)"))))
(deftest bad-link
(is (= "<p>[github](http://github.comfooo</p>"
(entry-function "[github](http://github.comfooo")))
(is (= "<p>[github] no way (http://github.com)</p>"
(entry-function "[github] no way (http://github.com)"))))
(deftest bad-link-title
(is (= "<p>[github(http://github.comfooo)</p>"
(entry-function "[github(http://github.comfooo)"))))
(deftest blockquote
(is (= "<blockquote><p>Foo bar baz </p></blockquote>"
(entry-function ">Foo bar baz"))))
(deftest blockquote-footer
(is (= "<blockquote><p> Foo bar baz </p><footer> Leo Tolstoy</footer></blockquote>"
(entry-function "> Foo bar baz\n>- Leo Tolstoy"))))
(deftest blockquote-empty-footer
(is (= "<blockquote><p> Foo bar baz </p><footer></footer></blockquote>"
(entry-function "> Foo bar baz\n>-"))))
(deftest blockquote-multiline-without-leading-angle-bracket
(is (= "<blockquote><p> Foo bar baz </p></blockquote>"
(entry-function "> Foo bar\nbaz"))))
(deftest blockquote-multiple-paragraphs
(is (= "<blockquote><p> Foo bar </p><p> baz </p></blockquote>"
(entry-function "> Foo bar\n>\n> baz"))))
(deftest blockquote-bullets
(is (= "<blockquote><p> list: <ul><li>foo</li><li>bar</li></ul></p></blockquote><p>end.</p>"
(entry-function "> list:\n>* foo\n>* bar\n\nend.")))
(is (= "<blockquote><p><ul><li>foo</li><li>bar</li><li>baz</li></ul></p></blockquote>"
(entry-function ">* foo\n>* bar\n>* baz"))))
(deftest blockquote-headings
(is (= "<blockquote><p><h2>Foo</h2>bar baz </p></blockquote>"
(entry-function "> ## Foo\n>bar baz")))
(is (= "<blockquote><p> Foo <h2>bar</h2> baz </p></blockquote>"
(entry-function "> Foo\n>## bar\n> baz"))))
(deftest escaped-characters
(is
(= "<p>&#94;&#42;&#8216;&#95;&#123;&#125;&#91;&#93;<em>foo</em><code>test</code><i>bar</i>{x}[y]</p>"
(entry-function "\\^\\*\\`\\_\\{\\}\\[\\]*foo*`test`_bar_{x}[y]"))))
(deftest paragraph-after-list
(is (= "<ol><li>a</li><li>b</li></ol><p>test <strong>bold</strong> and <em>italic</em></p>"
(entry-function "1. a\n2. b\n\ntest **bold** and *italic*"))))
(deftest paragraph-close-before-list
(is (= "<p>in paragraph</p><ul><li>list</li></ul>"
(entry-function "in paragraph\n- list"))))
(deftest autourl
(is (= "<p><a href=\"http://example.com/\">http://example.com/</a></p>"
(entry-function "<http://example.com/>")))
(is (= "<p>Some content with a <a href=\"http://www.google.com/abc__123__efg\">http://www.google.com/abc__123__efg</a> link it in</p>"
(entry-function "Some content with a <http://www.google.com/abc__123__efg> link it in")))
(is (= "<p><a href=\"http://foo\">http://foo</a> <a href=\"https://bar/baz\">https://bar/baz</a> <a href=\"http://foo/bar\">foo bar</a></p>"
(entry-function "<http://foo> <https://bar/baz> <a href=\"http://foo/bar\">foo bar</a>")))
#?(:bb nil :org.babashka/nbb nil
:default
(is (= "<p><a href=\"mailto:abc@google.com\">abc@google.com</a></p>"
(#?(:clj org.apache.commons.lang.StringEscapeUtils/unescapeHtml
:cljs goog.string/unescapeEntities)
(entry-function "<abc@google.com>")))))
#?(:bb nil :org.babashka/nbb nil
:default
(is (= "<p><a href=\"mailto:abc_def_ghi@google.com\">abc_def_ghi@google.com</a></p>"
(#?(:clj org.apache.commons.lang.StringEscapeUtils/unescapeHtml
:cljs goog.string/unescapeEntities)
(entry-function "<abc_def_ghi@google.com>"))))))
(deftest not-a-list
(is (= "<p>The fish was 192.8 lbs and was amazing to see.</p>"
(entry-function "The fish was\n192.8 lbs and was amazing to see."))))
(deftest dont-encode-chars-in-hrefs
(is (= "<p><a href='http://www.google.com/example_link_foo~_^*'>example_link with tilde ~ and carat ^ and splat *</a></p>"
(entry-function "[example_link with tilde ~ and carat ^ and splat *](http://www.google.com/example_link_foo~_^*)"))))
(deftest complex-link-with-terminal-encoding-inside-header
(is (= "<h2>With a link <a href='http://a.com/under_score_in_the_link/'>the contents of the_link</a></h2>"
(entry-function "##With a link [the contents of the_link](http://a.com/under_score_in_the_link/)"))))
(deftest two-links-tests-link-processing
(is (= "<h2>When you have a pair of links <a href='http://123.com/1'>link1</a> and you want both <a href='That%27s%20crazy'>Wow</a></h2>"
(entry-function "## When you have a pair of links [link1](http://123.com/1) and you want both [Wow](That%27s%20crazy)"))))
(deftest link-then-image-processing
(is (= "<p>You can have a <a href='github.com'>link</a> followed by an image <img src=\"img.png\" alt=\"\" /></p>"
(entry-function "You can have a [link](github.com) followed by an image ![](img.png)"))))
(deftest image-then-link-processing
(is (= "<p>You can have an image <img src=\"img.png\" alt=\"\" /> followed by a <a href='github.com'>link</a></p>"
(entry-function "You can have an image ![](img.png) followed by a [link](github.com)"))))
(deftest link-with-optional-title
(is (= "<p><a href='https://github.com/cryogen-project/cryogen' title=\"Cryogen Github\">Cryogens site</a></p>"
(entry-function "[Cryogens site](https://github.com/cryogen-project/cryogen \"Cryogen Github\")"))))
(deftest parse-table-row
(is (= (tables/parse-table-row "| table cell contents |") [{:text "table cell contents"}]))
(is (= (tables/parse-table-row "| contents 1 | contents 2 | contents 3 | contents 4 |")
[{:text "contents 1"} {:text "contents 2"} {:text "contents 3"} {:text "contents 4"}])))
(deftest table-row->str
(is (= (tables/table-row->str
[{:text "contents 1"} {:text "contents 2"} {:text "contents 3"} {:text "contents 4"}]
true)
"<th>contents 1</th><th>contents 2</th><th>contents 3</th><th>contents 4</th>"))
(is (= (tables/table-row->str
[{:text "contents 1"} {:text "contents 2"} {:text "contents 3"} {:text "contents 4"}]
false)
"<td>contents 1</td><td>contents 2</td><td>contents 3</td><td>contents 4</td>"))
(is (= (tables/table-row->str
[{:text "contents 1" :alignment :left}
{:text "contents 2" :alignment :center}
{:text "contents 3" :alignment :right}
{:text "contents 4"}]
false)
"<td style='text-align:left'>contents 1</td><td style='text-align:center'>contents 2</td><td style='text-align:right'>contents 3</td><td>contents 4</td>")))
(deftest table->str
(is (= (tables/table->str
{:alignment-seq
[{:alignment :left} {:alignment :center} {:alignment :right} {:alignment nil}]
:data [[{:text "Header 1"}
{:text "Header 2"}
{:text "Header 3"}
{:text "Header 4"}]
[{:text "contents 1"}
{:text "contents 2"}
{:text "contents 3"}
{:text "contents 4"}]]})
"<table><thead><tr><th style='text-align:left'>Header 1</th><th style='text-align:center'>Header 2</th><th style='text-align:right'>Header 3</th><th>Header 4</th></tr></thead><tbody><tr><td style='text-align:left'>contents 1</td><td style='text-align:center'>contents 2</td><td style='text-align:right'>contents 3</td><td>contents 4</td></tr></tbody></table>")))
(deftest divider-seq->alignment
(is (= (tables/divider-seq->alignment
[{:text "-----"} {:text ":-----"} {:text "-----:"} {:text ":-----:"}])
[nil {:alignment :left} {:alignment :right} {:alignment :center}])))
(deftest n-dash
(is (= "<p>boo &ndash; bar</p>" (entry-function "boo -- bar"))))
(deftest m-dash
(is (= "<p>boo &mdash; bar</p>" (entry-function "boo --- bar"))))
(deftest inhibit-simple
(is (= "<p>_abc_</p>" (entry-function "$_abc_$" :inhibit-separator "$"))))
(deftest inhibit-simple-seq
(is (= "<p>_abc_</p>" (entry-function "$_abc_$" :inhibit-separator [\$]))))
(deftest inhibit-inline-code
(is (= "<p>`abc`</p>" (entry-function "$`abc`$" :inhibit-separator [\$]))))
(deftest inhibit-inside-code
(is (= "<p><code>a*b* & dc</code></p>" (entry-function "`a$*b* & d$c`" :inhibit-separator "$"))))
(deftest inhibit-across-backticks
(is (= "<p><code>one` `two</code></p>" (entry-function "`one$` `$two`" :inhibit-separator "$"))))
(deftest inhibit-escape
(is (= "<p>$</p>" (entry-function "$$" :inhibit-separator [\$]))))
(deftest inhibit-escape-twice
(is (= "<p>$$</p>" (entry-function "$$$$" :inhibit-separator "$"))))
(deftest img-reprocess
(is (= "<p><img src=\"img.jpg\" alt=\"Text\" /> and <a href='#'>Edit</a></p>"
(entry-function "![Text](img.jpg) and [Edit](#)"))))
(deftest dont-inhibit-text-within-escapes
(is (= "<p>$<em>abc</em>$</p>" (entry-function "$$*abc*$$" :inhibit-separator "$"))))
(deftest inhibit-escape-inside-code
(is (= "<p><code>$</code></p>" (entry-function "`$$`" :inhibit-separator "$"))))
(deftest whitespace-paragraphs
(is (= "<p>foo </p><p>bar</p>" (entry-function "foo\n \nbar"))))

View file

@ -0,0 +1,10 @@
(ns nbb-runner
(:require [clojure.string :as str]
[clojure.test :refer [run-tests]]
[nbb.classpath :as cp]))
(cp/add-classpath (str/join ":" ["src/cljs" "src/cljc" "test"]))
(require '[markdown.md-test])
(run-tests 'markdown.md-test)

View file

@ -0,0 +1,5 @@
(ns markdown.runner
(:require [doo.runner :refer-macros [doo-tests]]
[markdown.md-test]))
(doo-tests 'markdown.md-test)