summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsko Nõmm <ano@ano.ee>2022-05-12 21:09:38 +0300
committerGitHub <noreply@github.com>2022-05-12 21:09:38 +0300
commit2ff0da12f58d17b6c1ab3736a41595073b3a534e (patch)
tree52dab7ba9cb71ca06c334cada0b8fc2c99c3fb91
parent94c1c0ca639f55ff9073cb1fdf2ad6015bb6bae1 (diff)
parentdc2a364db6d14d4afa9da9aadbccb8fdbb038fe4 (diff)
Merge pull request #31 from askonomm/7-support-indented-code-blocks
Implement indented code blocks.
-rw-r--r--resources/test/core.md8
-rw-r--r--resources/test/core_result.html8
-rw-r--r--src/clarktown/correctors.clj3
-rw-r--r--src/clarktown/correctors/atx_heading_block.clj2
-rw-r--r--src/clarktown/correctors/indented_code_block.clj57
-rw-r--r--src/clarktown/engine.clj8
-rw-r--r--src/clarktown/matchers/indented_code_block.clj10
-rw-r--r--src/clarktown/parsers.clj10
-rw-r--r--src/clarktown/renderers/indented_code_block.clj17
-rw-r--r--test/clarktown/correctors/atx_heading_block_test.clj2
-rw-r--r--test/clarktown/correctors/indented_code_block_test.clj30
-rw-r--r--test/clarktown/matchers/indented_code_block_test.clj13
-rw-r--r--test/clarktown/renderers/indented_code_block_test.clj14
13 files changed, 174 insertions, 8 deletions
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
-
+ <?php
+ echo 'indented code block';
+ ?>
***
* List item
@@ -87,6 +89,10 @@ code goes here.
This is a H1 heading with settext
=================================
+ <?php
+ echo 'indented code block';
+ ?>
+
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) {
<ul><li>List item</li><li>Another list <del>item</del><ul><li>Sub list item</li><li>Another sub list item<ul><li>Sub sub list item</li><li>Continuing sub list item</li></ul></li></ul></li><li>Continuing list item</li></ul>
+<pre><code>&lt;?php
+echo 'indented code block';
+?&gt;</code></pre>
+
<hr>
<ul><li>List item</li><li>Another list item<ul><li>Sub list item</li><li>Another sub list item<ol><li>Sub sub list item</li><li>Continuing sub list item</li></ol></li></ul></li><li>Continuing list item</li></ul>
@@ -61,6 +65,10 @@ function markdownToHTML(markdown) {
<h1 id="this-is-a-h1-heading-with-settext">This is a H1 heading with settext</h1>
+<pre><code>&lt;?php
+echo 'indented code block';
+?&gt;</code></pre>
+
<h2 id="and-this-is-a-h2-heading-with-settext">And this is a H2 heading with settext</h2>
<p>Testing paragraph right before a code block</p>
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]
@@ -61,6 +63,13 @@
(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
{:matcher clarktown.matchers.list-block/match?
@@ -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
+ "<pre><code>"
+ (-> (->> (string/split-lines block)
+ (map #(subs % 4))
+ (string/join \newline))
+ (string/replace #"&" "&amp;")
+ (string/replace #"<" "&lt;")
+ (string/replace #">" "&gt;"))
+ "</code></pre>")) \ No newline at end of file
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 (= "<pre><code>code goes here</code></pre>"
+ (indented-code-block/render " code goes here" nil nil))))
+
+ (testing "Creating a multi-line code block"
+ (is (= "<pre><code>code goes here\nand here</code></pre>"
+ (indented-code-block/render " code goes here\n and here" nil nil))))) \ No newline at end of file