diff options
| author | Asko Nõmm <asko@bien.ee> | 2022-04-21 19:13:02 +0300 |
|---|---|---|
| committer | Asko Nõmm <asko@bien.ee> | 2022-04-21 19:13:02 +0300 |
| commit | 04821d8be5d773153718948454c864495704f67b (patch) | |
| tree | 2b4bf3433ca40f30d0dbd282895e70021a769eda /src/clarktown/core.clj | |
| parent | a178a0b1867cb5194a1a2cd4f6e01ac261bfa4b7 (diff) | |
Send correctors to each render as well
Diffstat (limited to 'src/clarktown/core.clj')
| -rw-r--r-- | src/clarktown/core.clj | 143 |
1 files changed, 3 insertions, 140 deletions
diff --git a/src/clarktown/core.clj b/src/clarktown/core.clj index cabd6e6..a624275 100644 --- a/src/clarktown/core.clj +++ b/src/clarktown/core.clj @@ -1,147 +1,10 @@ (ns clarktown.core (:require - [clojure.string :as string] + [clarktown.engine :as engine] [clarktown.parsers :as parsers] [clarktown.correctors :as correctors])) -(defn- stitch-code-blocks - "Since code blocks can span multiple blocks (a block is separated by - two line breaks from another block) , we need to stitch them together - into one block in order for a block parser to be able to do anything - with it." - [blocks] - (loop [stitched-blocks [] - code-block-started? false - blocks blocks] - (if (empty? blocks) - stitched-blocks - (let [block (first blocks)] - (if (and (string/starts-with? (string/trim block) "```") - (not (string/ends-with? (string/trim block) "```"))) - (recur (conj stitched-blocks block) - true - (drop 1 blocks)) - (if code-block-started? - (let [last-block (last stitched-blocks) - last-block-index (- (count stitched-blocks) 1)] - (if (string/ends-with? (string/trim block) "```") - (recur (assoc stitched-blocks last-block-index (str last-block "\n\n" block)) - false - (drop 1 blocks)) - (recur (assoc stitched-blocks last-block-index (str last-block "\n\n" block)) - true - (drop 1 blocks)))) - (recur (conj stitched-blocks block) - false - (drop 1 blocks)))))))) - - -(defn- correct-block-separations - "Corrects block separations and adds newlines above or - below a block where needed." - [correctors lines] - (->> lines - (map-indexed - (fn [index line] - (let [add-line-above? (some #(true? (% lines line index)) (:empty-line-above? correctors)) - add-line-below? (some #(true? (% lines line index)) (:empty-line-below? correctors))] - (cond - ; If code block starts but there is no empty newline - ; above, let's fix that - (and add-line-above? - (not add-line-below?)) - (str \newline line) - - ; If the code block ends, but there is no empty newline - ; below, let's fix that. - (and add-line-below? - (not add-line-above?)) - (str line \newline) - - ; If the code block needs a newline both above and below, - ; let's fix that. - (and add-line-above? - add-line-below?) - (str \newline line \newline) - - ; otherwise is what it is - :else line)))))) - - -(defn- correct-markdown - "Corrects invalid Markdown for the parser." - [markdown given-correctors] - (let [lines (string/split-lines markdown)] - (->> lines - (correct-block-separations (:block-separations given-correctors)) - (string/join \newline)))) - - -(defn- find-parser-by-block - "Find a parser from `parsers` that matches the given `block`." - [parsers block] - (->> parsers - (filter - (fn [{:keys [matcher]}] - (when matcher - (matcher block)))) - first)) - - -(defn- parse-block-with-known-parser - "Parses a given `block` with a known `parser`." - [parser parsers block] - (loop [block block - renderers (:renderers parser)] - (if (empty? renderers) - block - (let [renderer (first renderers)] - (recur (renderer block parsers) - (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 - (recur (loop [block block - renderers (:renderers (first parsers))] - (if (empty? renderers) - block - (let [renderer (first renderers)] - (recur (renderer block parsers) - (drop 1 renderers))))) - (drop 1 parsers))))) - - -(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)] - (->> (string/trim block) - (parse-block-with-known-parser parser parsers)) - (->> (string/trim block) - (parse-block-with-unknown-parsers parsers))))) - - -(defn parse - "Parses given `markdown` with `parsers`." - [markdown given-parsers given-correctors] - (let [blocks (-> (correct-markdown markdown given-correctors) - (string/split #"\n\n") - stitch-code-blocks) - parsed-blocks (parse-blocks blocks given-parsers)] - (string/join "\n\n" 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. @@ -155,7 +18,7 @@ argument, which is a given Markdown block. An example parser: - ``` + ```clojure {:matcher (fn [block] ...) :renderers [(fn [block] ...) (fn [block] ...)]} ```" @@ -164,4 +27,4 @@ ([markdown given-parsers] (render markdown given-parsers correctors/default-correctors)) ([markdown given-parsers given-correctors] - (parse markdown given-parsers given-correctors)))
\ No newline at end of file + (engine/render markdown given-parsers given-correctors)))
\ No newline at end of file |
