Source file yocaml_omd.ml
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
let to_text elt =
let rec aux acc = function
| Omd.Text (_, value) | Omd.Code (_, value) -> acc ^ value
| Omd.Emph (_, inline) | Omd.Strong (_, inline) -> aux acc inline
| Omd.Link (_, { label; _ }) | Omd.Image (_, { label; _ }) -> aux acc label
| Omd.Hard_break _ | Omd.Soft_break _ -> "\n"
| Omd.Html _ -> acc
| Omd.Concat (_, inlines) -> List.fold_left aux acc inlines
in
aux "" elt
let tag l x = Format.asprintf "<%s>%s</%s>" l x l
let inline_to_html elt =
let rec aux acc = function
| Omd.Text (_, value) -> acc ^ value
| Omd.Code (_, value) -> acc ^ tag "code" value
| Omd.Emph (_, value) -> acc ^ tag "em" (aux "" value)
| Omd.Strong (_, value) -> acc ^ tag "strong" (aux "" value)
| Omd.Link (_, { label; _ }) -> acc ^ aux "" label
| Omd.Hard_break _ -> acc ^ "<br />"
| Omd.Soft_break _ -> acc ^ "\n"
| Omd.Html _ | Omd.Image _ -> acc
| Omd.Concat (_, inlines) -> List.fold_left aux acc inlines
in
aux "" elt
let rec without_links = function
| Omd.Concat (attr, inlines) ->
Omd.Concat (attr, List.map without_links inlines)
| Omd.Emph (attr, inline) -> Omd.Emph (attr, without_links inline)
| Omd.Strong (attr, inline) -> Omd.Strong (attr, without_links inline)
| Omd.Link (_, link) -> link.label
| Omd.Image (attr, link) ->
Omd.Image (attr, Omd.{ link with label = without_links link.label })
| Omd.(Hard_break _ | Soft_break _ | Html _ | Code _ | Text _) as inline ->
inline
let doc =
let , doc =
List.fold_left
(fun (, doc) -> function
| Omd.Heading (attributes, level, inline) ->
let hd_inline, id, new_attributes =
match List.assoc_opt "id" attributes with
| None ->
let id = Yocaml.Slug.from @@ to_text inline in
let inline = without_links inline in
(inline, id, ("id", id) :: attributes)
| Some id ->
let inline = without_links inline in
(inline, id, attributes)
in
( (level, (id, hd_inline)) :: headers
, Omd.Heading (new_attributes, level, inline) :: doc )
| x -> (headers, x :: doc))
([], []) doc
in
(List.rev headers, List.rev doc)
let to_html_with_toc =
let open Yocaml.Task in
lift (fun content -> content |> Omd.of_string |> collect_headers)
>>> first
(lift Yocaml.Markup.Toc.from_list
>>| Yocaml.Markup.Toc.to_html inline_to_html)
>>> second (lift Omd.to_html)
let to_html =
Yocaml.Task.lift (fun content -> content |> Omd.of_string |> Omd.to_html)
let content_to_html () = Yocaml.Task.second to_html
let content_to_html_with_toc f =
let open Yocaml.Task in
second to_html_with_toc >>| fun (m, (toc, doc)) -> (f m toc, doc)