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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
(* src/tdoc/tdoc_markdown.ml *)
(* Markdown generator for T-Doc *)
open Tdoc_types
let percent_encode_for_link (name : string) : string =
let buf = Buffer.create (String.length name) in
String.iter (fun c ->
match c with
| 'A' .. 'Z'
| 'a' .. 'z'
| '0' .. '9'
| '-'
| '_'
| '.'
| '~' -> Buffer.add_char buf c
| _ -> Printf.bprintf buf "%%%02X" (Char.code c)
) name;
Buffer.contents buf
let normalize_named_argument_syntax (line : string) : string =
let len = String.length line in
let buf = Buffer.create len in
let is_ident_start = function
| 'a' .. 'z' | 'A' .. 'Z' | '_' -> true
| _ -> false
in
let is_ident_char = function
| 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' -> true
| _ -> false
in
let rec copy_ident j =
if j < len && is_ident_char line.[j] then copy_ident (j + 1) else j
in
let rec skip_spaces j =
if j < len && line.[j] = ' ' then skip_spaces (j + 1) else j
in
let rec prev_non_space j =
if j < 0 then None
else if line.[j] = ' ' then prev_non_space (j - 1)
else Some line.[j]
in
let rec loop i =
if i >= len then ()
else if is_ident_start line.[i] then begin
let j = copy_ident (i + 1) in
let k = skip_spaces j in
let prev = prev_non_space (i - 1) in
if k < len && line.[k] = ':' && (prev = Some '(' || prev = Some ',') then begin
Buffer.add_substring buf line i (j - i);
Buffer.add_string buf " = ";
loop (skip_spaces (k + 1))
end else begin
Buffer.add_substring buf line i (j - i);
loop j
end
end else begin
Buffer.add_char buf line.[i];
loop (i + 1)
end
in
loop 0;
Buffer.contents buf
let generate_function_doc entry =
let buf = Buffer.create 1024 in
Printf.bprintf buf "# %s\n\n" entry.name;
if entry.description_brief <> "" then
Printf.bprintf buf "%s\n\n" entry.description_brief;
if entry.description_full <> "" then
Printf.bprintf buf "%s\n\n" entry.description_full;
if entry.params <> [] then begin
Printf.bprintf buf "## Parameters\n\n";
List.iter (fun (p : param_doc) ->
let type_str = match p.type_info with Some t -> " (`" ^ t ^ "`)" | None -> "" in
Printf.bprintf buf "- **%s**%s: %s\n\n" p.name type_str p.description
) entry.params;
Buffer.add_string buf "\n";
end;
begin match entry.return_value with
| Some r ->
Printf.bprintf buf "## Returns\n\n";
Printf.bprintf buf "%s\n\n" r.description
| None -> ()
end;
if entry.examples <> [] then begin
Printf.bprintf buf "## Examples\n\n```t\n";
List.iter (fun e -> Printf.bprintf buf "%s\n" (normalize_named_argument_syntax e)) entry.examples;
Printf.bprintf buf "```\n\n";
end;
if entry.see_also <> [] then begin
Printf.bprintf buf "## See Also\n\n";
let links =
List.map
(fun s -> Printf.sprintf "[%s](%s.html)" s (percent_encode_for_link s))
entry.see_also
in
Printf.bprintf buf "%s\n\n" (String.concat ", " links);
end;
Buffer.contents buf
let generate_index entries =
let buf = Buffer.create 1024 in
Printf.bprintf buf "# Function Reference\n\n";
Printf.bprintf buf "| Function | Description |\n";
Printf.bprintf buf "| --- | --- |\n";
List.iter (fun e ->
if e.is_export then
Printf.bprintf buf "| [%s](%s.html) | %s |\n"
e.name
(percent_encode_for_link e.name)
e.description_brief
) (List.sort (fun a b -> String.compare a.name b.name) entries);
Buffer.contents buf