-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmd.exs
104 lines (95 loc) · 2.19 KB
/
md.exs
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
defmodule MD do
def h(weight, text, opts \\ %{}) do
id = opts[:id]
id_tag = if id, do: "<a id='#{id}'></a>"
markup = String.duplicate("#", weight)
"#{markup} #{text} #{id_tag}\n"
end
def h1(txt), do: h(1, txt)
def h2(txt), do: h(2, txt)
def h3(txt), do: h(3, txt)
def h4(txt), do: h(4, txt)
def h5(txt), do: h(5, txt)
def h6(txt), do: h(6, txt)
def link(text, path), do: "[#{text}](#{path})"
def local_link(text, ref), do: link(text, "#" <> anchor(ref))
def ul(items) do
Enum.map(items, & "- #{&1}\n")
end
def anchor(header_title) do
%{
~r/\./ => "",
~r/'/ => "",
~r/:/ => "-",
~r/\s/ => "-",
}
|> Enum.reduce(String.downcase(header_title), fn {find, replace}, acc ->
String.replace(acc, find, replace)
end)
end
def code(text), do: "<code>#{text}</code>"
def indent(lines, n) do
padding = String.duplicate(" ", n)
lines
|> Stream.intersperse("\n")
|> Enum.join("")
|> String.splitter(["\n"])
|> Stream.map(fn line ->
if line != "" do
[padding, line]
else
""
end
end)
|> Stream.reject(& &1 == "")
|> Enum.intersperse("\n")
end
def table(headers, lines) do
n_cols = if headers do
tuple_size(headers)
else
lines
|> hd()
|> tuple_size()
end
all_lines = if headers, do: [headers | lines], else: lines
max_widths = Enum.map(0..(n_cols - 1), fn idx ->
all_lines
|> Stream.map(& &1 |> elem(idx) |> :erlang.iolist_to_binary() |> String.length())
|> Enum.max()
end)
table_header = if headers do
[
[
"| ",
headers
|> Tuple.to_list()
|> Enum.intersperse(" | "),
" |\n",
],
[
"|",
max_widths
|> Stream.map(& String.duplicate("-", &1 + 2))
|> Enum.intersperse("|"),
"|\n",
],
]
else
[]
end
[
table_header,
Enum.map(lines, fn tup ->
[
"| ",
tup
|> Tuple.to_list()
|> Stream.map(& " #{&1} ")
|> Enum.intersperse("|"),
" |\n",
]
end),
]
end
end