From 7c3eba77fd3de0e108efba94018233a57e66989e Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Wed, 11 May 2022 20:42:30 +0300 Subject: Implement indented code blocks. --- resources/test/core.md | 8 +++- resources/test/core_result.html | 8 ++++ src/clarktown/correctors.clj | 3 ++ src/clarktown/correctors/atx_heading_block.clj | 2 +- src/clarktown/correctors/indented_code_block.clj | 57 ++++++++++++++++++++++++ src/clarktown/engine.clj | 8 ++-- src/clarktown/matchers/indented_code_block.clj | 10 +++++ src/clarktown/parsers.clj | 10 +++++ src/clarktown/renderers/indented_code_block.clj | 17 +++++++ 9 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 src/clarktown/correctors/indented_code_block.clj create mode 100644 src/clarktown/matchers/indented_code_block.clj create mode 100644 src/clarktown/renderers/indented_code_block.clj diff --git a/resources/test/core.md b/resources/test/core.md index eefc4f7..5c42a7d 100644 --- a/resources/test/core.md +++ b/resources/test/core.md @@ -68,7 +68,9 @@ This is ___bold italic text___ and ***this is also***. *What about italic text t * Sub sub list item * Continuing sub list item * Continuing list item - + *** * List item @@ -87,6 +89,10 @@ code goes here. This is a H1 heading with settext ================================= + + And this is a H2 heading with settext ------------------------------------- diff --git a/resources/test/core_result.html b/resources/test/core_result.html index 01f91aa..8963e74 100644 --- a/resources/test/core_result.html +++ b/resources/test/core_result.html @@ -52,6 +52,10 @@ function markdownToHTML(markdown) { +
<?php
+echo 'indented code block';
+?>
+
@@ -61,6 +65,10 @@ function markdownToHTML(markdown) {

This is a H1 heading with settext

+
<?php
+echo 'indented code block';
+?>
+

And this is a H2 heading with settext

Testing paragraph right before a code block

diff --git a/src/clarktown/correctors.clj b/src/clarktown/correctors.clj index 6b7cc1c..cd5e7e8 100644 --- a/src/clarktown/correctors.clj +++ b/src/clarktown/correctors.clj @@ -1,6 +1,7 @@ (ns clarktown.correctors (:require [clarktown.correctors.fenced-code-block :as fenced-code-block] + [clarktown.correctors.indented-code-block :as indented-code-block] [clarktown.correctors.atx-heading-block :as atx-heading-block] [clarktown.correctors.list-block :as list-block])) @@ -10,10 +11,12 @@ default-block-separation-correctors {:newline-above [fenced-code-block/newline-above? + indented-code-block/newline-above? atx-heading-block/newline-above? list-block/newline-above?] :newline-below [fenced-code-block/newline-below? + indented-code-block/newline-below? atx-heading-block/newline-below? list-block/newline-below?]}) diff --git a/src/clarktown/correctors/atx_heading_block.clj b/src/clarktown/correctors/atx_heading_block.clj index 6668700..5a5f713 100644 --- a/src/clarktown/correctors/atx_heading_block.clj +++ b/src/clarktown/correctors/atx_heading_block.clj @@ -20,7 +20,7 @@ there's no empty newline above, we need to create one, and so this function must then return `true`." [lines line index] - (and (is-atx-heading? (string/trim line)) + (and (is-atx-heading? line) (> index 0) (not (= (-> (nth lines (- index 1)) string/trim) "")) diff --git a/src/clarktown/correctors/indented_code_block.clj b/src/clarktown/correctors/indented_code_block.clj new file mode 100644 index 0000000..47deeb7 --- /dev/null +++ b/src/clarktown/correctors/indented_code_block.clj @@ -0,0 +1,57 @@ +(ns clarktown.correctors.indented-code-block + (:require + [clojure.string :as string] + [clarktown.matchers.list-block :as list-block-matcher])) + + +(defn- in-code-block? + "Determines whether the current `line` is within a code block." + [lines index] + (->> (take index lines) + (filter #(string/starts-with? (string/trim %) "```")) + count + odd?)) + + +(defn newline-above? + "Determines whether there's a need for an empty new line + above the `line` at the current `index`. In the case of a + code block, which starts with three backticks (```), if there's + no empty newline above, we need to create one, and so this + function must then return `true`." + [lines line index] + (let [space-count (count (take-while #{\space} line)) + not-first? (> index 0) + prev-line (when not-first? + (nth lines (- index 1))) + space-count-prev-line (count (take-while #{\space} prev-line))] + (and (>= space-count 4) + not-first? + (not (in-code-block? lines index)) + (not (list-block-matcher/match? line)) + (not (list-block-matcher/match? prev-line)) + (not (>= space-count-prev-line 4)) + (not (= (-> prev-line + string/trim) + ""))))) + +(defn newline-below? + "Determines whether there's a need for an empty new line + below the `line` at the current `index`. In the case of a + code block, which ends with three backticks (```), if there's + no empty newline above, we need to create one, and so this + function must then return `true`." + [lines line index] + (let [space-count (count (take-while #{\space} line)) + not-last? (< index (- (count lines) 1)) + next-line (when not-last? + (nth lines (+ index 1))) + space-count-next-line (count (take-while #{\space} next-line))] + (and (>= space-count 4) + not-last? + (not (in-code-block? lines index)) + (not (list-block-matcher/match? line)) + (not (list-block-matcher/match? next-line)) + (not (>= space-count-next-line 4)) + (not (= (-> next-line + string/trim) ""))))) diff --git a/src/clarktown/engine.clj b/src/clarktown/engine.clj index 5eb22d5..dc07e9f 100644 --- a/src/clarktown/engine.clj +++ b/src/clarktown/engine.clj @@ -70,7 +70,7 @@ (defn- remove-excess-newlines - "Replaces all occurences of 3 or more concecutive newlines into + "Replaces all occurrences of 3 or more consecutive newlines into two newlines." [markdown] (string/replace markdown #"\n{3,}" "\n\n")) @@ -133,10 +133,8 @@ [blocks given-parsers given-correctors] (for [block blocks] (if-let [parser (find-parser-by-block given-parsers block)] - (->> (string/trim block) - (parse-block-with-known-parser parser given-parsers given-correctors)) - (->> (string/trim block) - (parse-block-with-unknown-parsers given-parsers given-correctors))))) + (parse-block-with-known-parser parser given-parsers given-correctors block) + (parse-block-with-unknown-parsers given-parsers given-correctors block)))) (defn render diff --git a/src/clarktown/matchers/indented_code_block.clj b/src/clarktown/matchers/indented_code_block.clj new file mode 100644 index 0000000..b7cf563 --- /dev/null +++ b/src/clarktown/matchers/indented_code_block.clj @@ -0,0 +1,10 @@ +(ns clarktown.matchers.indented-code-block + (:require + [clojure.string :as string])) + + +(defn match? + "Determines whether the given block is a indented code block." + [block] + (->> (string/split-lines block) + (every? #(>= (count (take-while #{\space} %)) 4)))) \ No newline at end of file diff --git a/src/clarktown/parsers.clj b/src/clarktown/parsers.clj index 0d3b019..8ca27b3 100644 --- a/src/clarktown/parsers.clj +++ b/src/clarktown/parsers.clj @@ -10,6 +10,8 @@ [clarktown.renderers.quote-block] [clarktown.matchers.fenced-code-block] [clarktown.renderers.fenced-code-block] + [clarktown.matchers.indented-code-block] + [clarktown.renderers.indented-code-block] [clarktown.matchers.list-block] [clarktown.renderers.list-block] [clarktown.renderers.paragraph-block] @@ -60,6 +62,13 @@ :renderers [clarktown.renderers.fenced-code-block/render]}) +(def + ^{:doc "Detects, parses and renders a indented code block."} + indented-code-block-parser + {:matcher clarktown.matchers.indented-code-block/match? + :renderers [clarktown.renderers.indented-code-block/render]}) + + (def ^{:doc "Detects, parses and renders a list block."} list-block-parser @@ -91,5 +100,6 @@ heading-block-parser quote-block-parser fenced-code-block-parser + indented-code-block-parser list-block-parser paragraph-block-parser]) diff --git a/src/clarktown/renderers/indented_code_block.clj b/src/clarktown/renderers/indented_code_block.clj new file mode 100644 index 0000000..b3828ec --- /dev/null +++ b/src/clarktown/renderers/indented_code_block.clj @@ -0,0 +1,17 @@ +(ns clarktown.renderers.indented-code-block + (:require + [clojure.string :as string])) + + +(defn render + "Renders the indented code block." + [block _ _] + (str + "
"
+    (-> (->> (string/split-lines block)
+             (map #(subs % 4))
+             (string/join \newline))
+        (string/replace #"&" "&")
+        (string/replace #"<" "<")
+        (string/replace #">" ">"))
+    "
")) \ No newline at end of file -- cgit v1.2.3 From dc2a364db6d14d4afa9da9aadbccb8fdbb038fe4 Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Thu, 12 May 2022 21:07:14 +0300 Subject: Add tests --- .../correctors/atx_heading_block_test.clj | 2 +- .../correctors/indented_code_block_test.clj | 30 ++++++++++++++++++++++ .../matchers/indented_code_block_test.clj | 13 ++++++++++ .../renderers/indented_code_block_test.clj | 14 ++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/clarktown/correctors/indented_code_block_test.clj create mode 100644 test/clarktown/matchers/indented_code_block_test.clj create mode 100644 test/clarktown/renderers/indented_code_block_test.clj diff --git a/test/clarktown/correctors/atx_heading_block_test.clj b/test/clarktown/correctors/atx_heading_block_test.clj index f363ad0..9889a9e 100644 --- a/test/clarktown/correctors/atx_heading_block_test.clj +++ b/test/clarktown/correctors/atx_heading_block_test.clj @@ -4,7 +4,7 @@ [clarktown.correctors.atx-heading-block :as corrector])) -(deftest atx-heading-block-corrector +(deftest atx-heading-block-corrector-test (testing "Empty line above" (let [line "# Hello" lines ["Some text goes here" line] diff --git a/test/clarktown/correctors/indented_code_block_test.clj b/test/clarktown/correctors/indented_code_block_test.clj new file mode 100644 index 0000000..fc4bcf0 --- /dev/null +++ b/test/clarktown/correctors/indented_code_block_test.clj @@ -0,0 +1,30 @@ +(ns clarktown.correctors.indented-code-block-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.correctors.indented-code-block :as corrector])) + + +(deftest indented-code-block-corrector-test + (testing "Empty line above" + (let [line " Test" + lines ["Some text goes here" line] + index 1] + (is (true? (corrector/newline-above? lines line index))))) + + (testing "No empty line above" + (let [line " Hello" + lines ["Some text goes here" "\n" line] + index 2] + (is (false? (corrector/newline-above? lines line index))))) + + (testing "Empty line below" + (let [line " Hello" + lines [line "Some text goes here"] + index 0] + (is (true? (corrector/newline-below? lines line index))))) + + (testing "No empty line below" + (let [line " Hello" + lines [line "\n" "Some text goes here"] + index 0] + (is (false? (corrector/newline-below? lines line index)))))) diff --git a/test/clarktown/matchers/indented_code_block_test.clj b/test/clarktown/matchers/indented_code_block_test.clj new file mode 100644 index 0000000..beffcaa --- /dev/null +++ b/test/clarktown/matchers/indented_code_block_test.clj @@ -0,0 +1,13 @@ +(ns clarktown.matchers.indented-code-block-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.matchers.indented-code-block :as code-block])) + + +(deftest indented-code-block-matcher-test + (testing "Checking a indented code block" + (is (true? (code-block/match? " blabla"))) + (is (true? (code-block/match? " abc\n dfg\n blabla"))) + (is (false? (code-block/match? " abc\n asdasd"))))) + + diff --git a/test/clarktown/renderers/indented_code_block_test.clj b/test/clarktown/renderers/indented_code_block_test.clj new file mode 100644 index 0000000..879284d --- /dev/null +++ b/test/clarktown/renderers/indented_code_block_test.clj @@ -0,0 +1,14 @@ +(ns clarktown.renderers.indented-code-block-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.renderers.indented-code-block :as indented-code-block])) + + +(deftest indented-code-block-renderer-test + (testing "Creating a single-line code block" + (is (= "
code goes here
" + (indented-code-block/render " code goes here" nil nil)))) + + (testing "Creating a multi-line code block" + (is (= "
code goes here\nand here
" + (indented-code-block/render " code goes here\n and here" nil nil))))) \ No newline at end of file -- cgit v1.2.3