-
-
Notifications
You must be signed in to change notification settings - Fork 120
/
lists.cljc
82 lines (64 loc) · 2.72 KB
/
lists.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(ns markdown.lists
(:require [clojure.string :as string]
[markdown.common :refer [*substring* make-heading]]))
(defn close-lists [lists]
(string/join
(for [[list-type] lists]
(str "</li></" (name list-type) ">"))))
(defn add-row [row-type list-type num-indents indents content state]
(if list-type
(cond
(< num-indents indents)
(let [lists-to-close (take-while #(> (second %) num-indents) (reverse (:lists state)))
remaining-lists (vec (drop-last (count lists-to-close) (:lists state)))]
[(apply str (close-lists lists-to-close) "</li><li>" content)
(assoc state :lists (if (> num-indents (second (last remaining-lists)))
(conj remaining-lists [row-type num-indents])
remaining-lists))])
(> num-indents indents)
[(str "<" (name row-type) "><li>" content)
(update-in state [:lists] conj [row-type num-indents])]
(= num-indents indents)
[(str "</li><li>" content) state])
[(str "<" (name row-type) "><li>" content)
(assoc state :lists [[row-type num-indents]])]))
(defn ul [text state]
(let [[list-type indents] (last (:lists state))
num-indents (count (take-while (partial = \space) text))
content (string/trim (*substring* text (inc num-indents)))]
(add-row :ul list-type num-indents indents (or (make-heading content false) content) state)))
(defn ol [text state]
(let [[list-type indents] (last (:lists state))
num-indents (count (take-while (partial = \space) text))
content (string/trim (string/join (drop-while (partial not= \space) (string/trim text))))]
(add-row :ol list-type num-indents indents (or (make-heading content false) content) state)))
(defn li [text {:keys [codeblock last-line-empty? eof lists] :as state}]
(cond
codeblock
[text state]
(and last-line-empty? (string/blank? text))
[(str (close-lists (reverse lists)) text)
(-> state (dissoc :lists) (assoc :last-line-empty? false))]
(and lists codeblock)
[text state]
(and (not eof)
lists
(string/blank? text))
[text (assoc state :last-line-empty? false :eof false)]
:else
(let [indents (if last-line-empty? 0 (count (take-while (partial = \space) text)))
trimmed (string/trim text)
in-list? (:lists state)]
(cond
(re-find #"^[\*\+-] " trimmed)
(ul text state)
(re-find #"^[0-9]+\. " trimmed)
(ol text state)
(pos? indents)
[text state]
(and (or eof last-line-empty?)
(not-empty lists))
[(close-lists (reverse lists))
(assoc state :lists [] :buf text)]
:else
[text state]))))