summaryrefslogtreecommitdiff
path: root/src/clarktown
diff options
context:
space:
mode:
Diffstat (limited to 'src/clarktown')
-rw-r--r--src/clarktown/core.clj96
-rw-r--r--src/clarktown/parsers/empty_block.clj13
-rw-r--r--src/clarktown/parsers/heading_block.clj13
3 files changed, 122 insertions, 0 deletions
diff --git a/src/clarktown/core.clj b/src/clarktown/core.clj
new file mode 100644
index 0000000..436b782
--- /dev/null
+++ b/src/clarktown/core.clj
@@ -0,0 +1,96 @@
+(ns clarktown.core
+ (:require
+ [clojure.string :as string]
+ [clarktown.parsers.empty-block :as empty-block]
+ [clarktown.parsers.heading-block :as heading-block]))
+
+
+(def default-parsers
+ [{:matcher empty-block/is?
+ :renderers [empty-block/render]}
+ {:matcher heading-block/is?
+ :renderers [heading-block/render]}])
+
+
+(defn find-parser-by-block
+ "Find a parser from `parsers` that matches the given `block`."
+ [parsers block]
+ (->> parsers
+ (filter
+ (fn [{:keys [matcher]}]
+ (matcher block)))
+ first))
+
+
+(defn parse-block-with-known-parser
+ "Parses a given `block` with a known `parser`."
+ [parser block]
+ (loop [block block
+ renderers (:renderers parser)]
+ (if (empty? renderers)
+ block
+ (let [renderer (first renderers)]
+ (recur (renderer block)
+ (drop 1 renderers))))))
+
+
+(defn- parse-block-with-unknown-parsers
+ "Parses the given `block` with all the parsers that do not have
+ a matcher function, useful for any fallback parsing one might want
+ to do."
+ [parsers block]
+ (loop [block block
+ parsers (filter #(= nil (:matcher %)) parsers)]
+ (if (empty? parsers)
+ block
+ (loop [block block
+ renderers (:renderers (first parsers))]
+ (if (empty? renderers)
+ block
+ (let [renderer (first renderers)]
+ (recur (renderer block)
+ (drop 1 renderers))))))))
+
+
+(defn- parse-blocks
+ "Parses each individual Markdown block, given as `blocks`, with
+ the list of `parsers`."
+ [blocks parsers]
+ (for [block blocks]
+ (if-let [parser (find-parser-by-block parsers block)]
+ (parse-block-with-known-parser parser block)
+ (parse-block-with-unknown-parsers parsers block))))
+
+
+(defn- parse
+ "Parses given `markdown` with `parsers`."
+ [markdown parsers]
+ (let [blocks (string/split markdown #"\n\n")
+ parsed-blocks (parse-blocks blocks parsers)]
+ (string/join "" parsed-blocks)))
+
+
+(defn render
+ "Renders the given `markdown` into a consumable HTML form. Optionally,
+ a second argument can be passed that is made out of a vector of parsers.
+
+ A parser is a map that consists of two things;
+ - A matcher (optional) , which returns a truthy or falsey value
+ - Renderers, which will be run on the a block when matcher returns true.
+ There can be any number of renderers.
+
+ Each matcher, and each renderer have to be a function that take a single
+ argument, which is a given Markdown block.
+
+ An example parser:
+ ```
+ {:matcher (fn [block] ...)
+ :renderers [(fn [block] ...) (fn [block] ...)]}
+ ```"
+ ([markdown]
+ (render markdown default-parsers))
+ ([markdown parsers]
+ (parse markdown parsers)))
+
+
+(render (slurp "/Users/asko/Documents/work/clarktown/test.md"))
diff --git a/src/clarktown/parsers/empty_block.clj b/src/clarktown/parsers/empty_block.clj
new file mode 100644
index 0000000..889c9ae
--- /dev/null
+++ b/src/clarktown/parsers/empty_block.clj
@@ -0,0 +1,13 @@
+(ns clarktown.parsers.empty-block
+ (:require
+ [clojure.string :as string]))
+
+
+(defn is?
+ [block]
+ (string/blank? (string/trim block)))
+
+
+(defn render
+ [block]
+ "emptyblockgoeshere")
diff --git a/src/clarktown/parsers/heading_block.clj b/src/clarktown/parsers/heading_block.clj
new file mode 100644
index 0000000..588d196
--- /dev/null
+++ b/src/clarktown/parsers/heading_block.clj
@@ -0,0 +1,13 @@
+(ns clarktown.parsers.heading-block
+ (:require
+ [clojure.string :as string]))
+
+(defn is?
+ [block]
+ (= true (-> (clojure.string/trim block)
+ (string/starts-with? "#"))))
+
+
+(defn render
+ [block]
+ "headingblock")