@@ -26,13 +26,12 @@ defmodule Helper.Converter.MdToEditor do
26
26
defp parse_block ( { type , _opt , content } )
27
27
when type in @ supported_header do
28
28
content_text =
29
- Enum . reduce ( content , [ ] , fn content_item , acc ->
29
+ Enum . reduce ( content , "" , fn content_item , acc ->
30
30
parsed = parse_inline ( type , content_item )
31
- acc ++ parsed
31
+ acc <> parsed
32
32
end )
33
33
34
34
# IO.inspect(content_text, label: "h-type content_text")
35
-
36
35
[ _ , level ] = String . split ( type , "h" )
37
36
level = String . to_integer ( level )
38
37
@@ -46,11 +45,28 @@ defmodule Helper.Converter.MdToEditor do
46
45
end
47
46
48
47
# parse markdown paragraph to editor's paragraph
48
+ # parse image
49
+ defp parse_block ( { "p" , _opt , [ { "img" , [ { "src" , src } , _alt ] , [ ] } ] } ) do
50
+ % {
51
+ type: "image" ,
52
+ data: % {
53
+ file: % {
54
+ url: src
55
+ } ,
56
+ caption: "" ,
57
+ withBorder: false ,
58
+ stretched: false ,
59
+ withBackground: false
60
+ }
61
+ }
62
+ end
63
+
49
64
defp parse_block ( { "p" , _opt , content } ) do
50
65
content_text =
51
- Enum . reduce ( content , [ ] , fn content_item , acc ->
66
+ Enum . reduce ( content , "" , fn content_item , acc ->
52
67
parsed = parse_inline ( "p" , content_item )
53
- acc ++ parsed
68
+
69
+ acc <> parsed
54
70
end )
55
71
56
72
% {
@@ -61,33 +77,150 @@ defmodule Helper.Converter.MdToEditor do
61
77
}
62
78
end
63
79
80
+ defp parse_block ( { "ul" , [ ] , content } ) do
81
+ case is_checklist_ul? ( content ) do
82
+ # normal ul list
83
+ false ->
84
+ items =
85
+ Enum . reduce ( content , [ ] , fn content_item , acc ->
86
+ parsed = parse_inline ( content_item )
87
+ acc ++ [ parsed ]
88
+ end )
89
+
90
+ % {
91
+ type: "list" ,
92
+ data: % {
93
+ style: "unordered" ,
94
+ items: items
95
+ }
96
+ }
97
+
98
+ # checklist
99
+ true ->
100
+ items =
101
+ Enum . reduce ( content , [ ] , fn content_item , acc ->
102
+ parsed = parse_inline ( content_item )
103
+
104
+ acc ++
105
+ [
106
+ % {
107
+ # 4 表示 [ ] 或 [x] 占用的 4 个 size
108
+ "text" => String . slice ( parsed , 4 , byte_size ( parsed ) ) ,
109
+ "checked" => String . starts_with? ( parsed , [ "[x] " , "[X] " ] )
110
+ }
111
+ ]
112
+ end )
113
+
114
+ % {
115
+ type: "checklist" ,
116
+ data: % {
117
+ items: items
118
+ }
119
+ }
120
+ end
121
+ end
122
+
123
+ defp parse_block ( { "ol" , [ ] , content } ) do
124
+ items =
125
+ Enum . reduce ( content , [ ] , fn content_item , acc ->
126
+ parsed = parse_inline ( content_item )
127
+ acc ++ [ parsed ]
128
+ end )
129
+
130
+ % {
131
+ type: "list" ,
132
+ data: % {
133
+ style: "ordered" ,
134
+ items: items
135
+ }
136
+ }
137
+ end
138
+
139
+ defp parse_block ( { "blockquote" , _opt , content } ) do
140
+ % {
141
+ type: "quote" ,
142
+ data: % {
143
+ text: parse_inline ( content )
144
+ }
145
+ }
146
+ end
147
+
148
+ defp parse_block ( { "hr" , _opt , _content } ) do
149
+ % {
150
+ type: "delimiter" ,
151
+ data: { }
152
+ }
153
+ end
154
+
64
155
defp parse_block ( { _type , _opt , _content } ) do
65
156
# IO.inspect(name, label: "parse block")
66
157
# IO.inspect(content, label: "content")
67
158
% { }
68
159
end
69
160
70
161
# 字符串直接返回,作为 editor.js 中的 text/data/code 等字段
71
- defp parse_inline ( content ) when is_binary ( content ) do
72
- content
162
+ defp parse_inline ( content ) when is_binary ( content ) , do: content
163
+ defp parse_inline ( [ _type , content ] ) , do: parse_inline ( content )
164
+ defp parse_inline ( [ content ] ) when is_binary ( content ) , do: parse_inline ( content )
165
+
166
+ defp parse_inline ( { "strong" , [ ] , content } ) do
167
+ "<b>#{ parse_inline ( content ) } </b>"
73
168
end
74
169
75
- # TODO: editor.js 暂时不支持 del 标签,所以直接返回字符串内容即可
76
- defp parse_inline ( { "del" , [ ] , [ content ] } ) do
77
- content
170
+ # NOTE: editor.js 暂时不支持 del 标签,所以直接返回字符串内容即可
171
+ # TODO: del -> editor.s marker
172
+ defp parse_inline ( { "del" , [ ] , [ content ] } ) , do: content
173
+ # NOTE: earmark parse italic as em
174
+ defp parse_inline ( { "em" , [ ] , [ content ] } ) , do: inline_res ( "em" , content )
175
+ defp parse_inline ( { "em" , [ ] , content } ) , do: inline_res ( "em" , content )
176
+ defp parse_inline ( [ { "em" , [ ] , content } ] ) , do: inline_res ( "em" , content )
177
+
178
+ defp parse_inline ( { "li" , [ ] , content } ) when is_list ( content ) do
179
+ line =
180
+ Enum . reduce ( content , "" , fn content_item , acc ->
181
+ acc <> parse_inline ( content_item )
182
+ end )
183
+
184
+ line
78
185
end
79
186
80
- defp parse_inline ( _type , content ) when is_binary ( content ) do
81
- content
187
+ defp parse_inline ( { "li" , [ ] , content } ) , do: parse_inline ( content )
188
+
189
+ defp parse_inline ( [ { "p" , [ ] , content } ] ) do
190
+ line =
191
+ Enum . reduce ( content , "" , fn content_item , acc ->
192
+ acc <> parse_inline ( content_item )
193
+ end )
194
+
195
+ line
82
196
end
83
197
84
- defp parse_inline ( type , { _type , _opt , [ content ] } )
85
- when type in @ supported_header do
198
+ defp parse_inline ( { "code" , [ { "class" , "inline" } ] , content } ) , do: inline_res ( "code" , content )
199
+ defp parse_inline ( [ { "code" , [ { "class" , "inline" } ] , content } ] ) , do: inline_res ( "code" , content )
200
+
201
+ defp parse_inline ( { "a" , [ { "href" , href } ] , [ content ] } ) do
202
+ "<a href=\" #{ href } \" >#{ content } </a>"
203
+ end
204
+
205
+ defp inline_res ( "em" , content ) , do: "<i>#{ parse_inline ( content ) } </i>"
206
+
207
+ defp inline_res ( "code" , content ) ,
208
+ do: "<code class=\" inline-code\" >#{ parse_inline ( content ) } </code>"
209
+
210
+ defp parse_inline ( _type , content ) when is_binary ( content ) , do: content
211
+
212
+ defp parse_inline ( header , { _type , _opt , [ content ] } )
213
+ when header in @ supported_header do
86
214
parse_inline ( content )
87
215
end
88
216
89
- # defp parse_inline({type, _opt, content})
90
- # when type == "h1" or type == "h2" or type == "h3" do
91
- # content
92
- # end
217
+ # when header in @supported_header do
218
+ defp parse_inline ( "p" , content ) , do: parse_inline ( content )
219
+
220
+ # 判断是否为 editorjs 的 checklist
221
+ defp is_checklist_ul? ( content ) when is_list ( content ) do
222
+ Enum . all? ( content , fn { "li" , [ ] , li_item } ->
223
+ li_item |> Enum . at ( 0 ) |> String . starts_with? ( [ "[ ] " , "[x] " , "[X] " ] )
224
+ end )
225
+ end
93
226
end