@@ -67,7 +67,7 @@ and transform = function
67
67
from omd 1.3.1 source.
68
68
https://github.com/ocaml/omd/blob/1.3.1/src/omd_backend.ml#L872
69
69
*)
70
- let mrkdwn_of_md md =
70
+ let rec mrkdwn_of_md md =
71
71
let b = Buffer. create 128 in
72
72
let references : ref_container option ref = ref None in
73
73
let nl b = Buffer. add_char b '\n' in
@@ -87,9 +87,31 @@ let mrkdwn_of_md md =
87
87
which is inside a list item because those need to be indented!
88
88
* )
89
89
| X _ -> loop list_indent tl
90
- | Blockquote _q -> (* todo *) loop list_indent tl
90
+ | Blockquote q ->
91
+ (* mrkdwn doesn't support nested quotes, but output '>' chars anyway*)
92
+ let quote s =
93
+ let b = Buffer. create (String. length s) in
94
+ let l = String. length s in
95
+ let rec loop is_nl i =
96
+ if i < l then begin
97
+ if is_nl && i < l - 1 then Buffer. add_string b " > " ;
98
+ match s.[i] with
99
+ | '\n' ->
100
+ nl b;
101
+ loop true (i + 1 )
102
+ | c ->
103
+ Buffer. add_char b c;
104
+ loop false (i + 1 )
105
+ end
106
+ else Buffer. contents b
107
+ in
108
+ loop true 0
109
+ in
110
+ Buffer. add_string b (quote @@ mrkdwn_of_md q);
111
+ if not @@ List. is_empty tl then nl_if_needed_above b;
112
+ loop list_indent tl
91
113
| Ref (rc , _name , _text , fallback ) | Img_ref (rc , _name , _text , fallback ) ->
92
- (* [rc] stores refs from whole document, so it's enough to record just the
114
+ (* [rc] stores all refs from document, so it's enough to record just the
93
115
first encounter
94
116
*)
95
117
if Option. is_empty ! references then references := Some rc;
@@ -162,21 +184,37 @@ let mrkdwn_of_md md =
162
184
Printf. bprintf b " %d. " i;
163
185
loop ~is_in_list: true (list_indent + 4 ) li (* Paragraphs => No need of '\n' *) );
164
186
loop list_indent tl
165
- | Code_block (_lang , _c ) -> (* todo *) loop list_indent tl
187
+ | Code_block (_lang , c ) ->
188
+ (* unlike commonmark, can't have code block inside lists, so print code block with
189
+ zero indent, but continue rest of the list at correct indent after
190
+
191
+ note: sometimes indentation intended as list item paragraph is wrongly
192
+ interpreted as code block - an issue with Omd.of_string
193
+ e.g., both should be parsed the second way, but aren't:
194
+ # of_string " - foo\n\n bar";;
195
+ - : t = [Ul [[Text "foo"]]; NL; NL; Code_block ("", "bar")]
196
+ # of_string "- foo\n\n bar";;
197
+ - : t = [Ulp [[Paragraph [Text "foo"]; Paragraph [Text "bar"]]]]
198
+ *)
199
+ nl_if_needed_above b;
200
+ Buffer. add_string b " ```\n " ;
201
+ Buffer. add_string b (escape_mrkdwn c);
202
+ nl_if_needed_above b;
203
+ Buffer. add_string b " ```\n " ;
204
+ loop list_indent tl
166
205
| Code (_lang , c ) ->
206
+ (* sadly, slack mrkdwn has no way to escape backticks within in-line code,
207
+ so broken markup is unavoidable
208
+ *)
167
209
Buffer. add_char b '`' ;
168
210
Buffer. add_string b (escape_mrkdwn c);
169
211
Buffer. add_char b '`' ;
170
212
loop list_indent tl
171
213
| Hr ->
172
214
Buffer. add_string b " * * *\n " ;
173
215
loop list_indent tl
174
- | Html (tagname , _attrs , body ) ->
175
- Printf. bprintf b " `<%s>" tagname;
176
- Buffer. add_string b (escape_mrkdwn @@ to_html body);
177
- Printf. bprintf b " </%s>`" tagname;
178
- loop list_indent tl
179
- | Html_block (_tagname , _attrs , _body ) -> (* todo *) loop list_indent tl
216
+ | Html (_tagname , _attrs , _body ) as html -> loop list_indent (Code (" " , to_html [ html ]) :: tl)
217
+ | Html_block (_tagname , _attrs , _body ) as html -> loop list_indent (Code_block (" " , to_html [ html ]) :: tl)
180
218
| Html_comment _s -> loop list_indent tl
181
219
| Url (href , s , title ) ->
182
220
Buffer. add_char b '<' ;
0 commit comments