this repo has no description
at main 190 lines 6.6 kB view raw
1open Odoc_utils 2open Odoc_model 3 4(* Selective opens *) 5module Id = Odoc_model.Paths.Identifier 6module PageName = Odoc_model.Names.PageName 7module ModuleName = Odoc_model.Names.ModuleName 8 9type t = Entry.t Tree.t 10 11let compare_entry (t1 : t) (t2 : t) = 12 let by_kind (t : t) = 13 match t.node.kind with 14 | Page _ | Dir -> 0 15 | Module _ -> 10 16 | Impl -> 20 17 | _ -> 30 18 in 19 let by_category (t : t) = 20 match t.node.kind with 21 | Page { order_category = Some o; _ } -> o 22 | _ -> "default" 23 in 24 let by_name (t : t) = 25 match t.node.kind with 26 | Page { short_title = Some title; _ } -> Comment.to_string title 27 | _ -> ( 28 match t.node.id.iv with 29 | `LeafPage (Some parent, name) 30 when Names.PageName.to_string name = "index" -> 31 Id.name parent 32 | _ -> Id.name t.node.id) 33 in 34 let try_ comp f fallback = 35 match comp (f t1) (f t2) with 0 -> fallback () | i -> i 36 in 37 try_ (compare : int -> int -> int) by_kind @@ fun () -> 38 try_ Astring.String.compare by_category @@ fun () -> 39 try_ Astring.String.compare by_name @@ fun () -> 0 40 41let rec t_of_in_progress (dir : In_progress.in_progress) : t = 42 let entry_of_page page = 43 let kind = Entry.Page page.Lang.Page.frontmatter in 44 let doc = page.content.elements in 45 let id = page.name in 46 Entry.entry ~kind ~doc ~id ~source_loc:None 47 in 48 let entry_of_impl id = 49 let kind = Entry.Impl in 50 Entry.entry ~kind ~doc:[] ~id ~source_loc:None 51 in 52 let children_order, index = 53 match In_progress.index dir with 54 | Some (_, page) -> 55 let children_order = page.frontmatter.children_order in 56 let entry = entry_of_page page in 57 (children_order, entry) 58 | None -> 59 let entry = 60 match In_progress.root_dir dir with 61 | Some id -> 62 let kind = Entry.Dir in 63 Entry.entry ~kind ~doc:[] ~id ~source_loc:None 64 | None -> 65 let id = 66 (* root dir must have an index page *) 67 Id.Mk.leaf_page (None, Names.PageName.make_std "index") 68 in 69 let kind = Entry.Dir in 70 Entry.entry ~kind ~doc:[] ~id ~source_loc:None 71 in 72 (None, entry) 73 in 74 let pp_content fmt (id, _) = 75 match id.Id.iv with 76 | `LeafPage (_, name) -> Format.fprintf fmt "'%s'" (PageName.to_string name) 77 | `Page (_, name) -> Format.fprintf fmt "'%s/'" (PageName.to_string name) 78 | `Root (_, name) -> 79 Format.fprintf fmt "'module-%s'" (ModuleName.to_string name) 80 | _ -> Format.fprintf fmt "'unsupported'" 81 in 82 let pp_children fmt c = 83 match c.Location_.value with 84 | Frontmatter.Page s -> Format.fprintf fmt "'%s'" s 85 | Dir s -> Format.fprintf fmt "'%s/'" s 86 | Module s -> Format.fprintf fmt "'module-%s'" s 87 in 88 let ordered, unordered = 89 let contents = 90 let leafs = 91 In_progress.leafs dir 92 |> List.map (fun (_, page) -> 93 let id :> Id.t = page.Lang.Page.name in 94 let entry = entry_of_page page in 95 (id, Tree.leaf entry)) 96 in 97 let dirs = 98 In_progress.dirs dir 99 |> List.map (fun (id, payload) -> 100 let id :> Id.t = id in 101 (id, t_of_in_progress payload)) 102 in 103 let modules = 104 In_progress.modules dir 105 |> List.map (fun (id, payload) -> ((id :> Id.t), payload)) 106 in 107 let implementations = 108 In_progress.implementations dir 109 |> List.map (fun (id, _impl) -> 110 ((id :> Id.t), Tree.leaf @@ entry_of_impl id)) 111 in 112 leafs @ dirs @ modules @ implementations 113 in 114 match children_order with 115 | None -> ([], contents) 116 | Some children_order -> 117 let children_indexes = 118 List.mapi (fun i x -> (i, x)) children_order.value 119 in 120 let equal id ch = 121 match (ch, id.Id.iv) with 122 | (_, { Location_.value = Frontmatter.Dir c; _ }), `Page (_, name) -> 123 Astring.String.equal (PageName.to_string name) c 124 | (_, { Location_.value = Page c; _ }), `LeafPage (_, name) -> 125 Astring.String.equal (PageName.to_string name) c 126 | (_, { Location_.value = Module c; _ }), `Root (_, name) -> 127 Astring.String.equal (ModuleName.to_string name) c 128 | _ -> false 129 in 130 let children_indexes, indexed_content, unindexed_content = 131 List.fold_left 132 (fun (children_indexes, indexed_content, unindexed_content) 133 ((id, _) as entry) -> 134 let indexes_for_entry, children_indexes = 135 List.partition (equal id) children_indexes 136 in 137 match indexes_for_entry with 138 | [] -> 139 (children_indexes, indexed_content, entry :: unindexed_content) 140 | (i, _) :: rest -> 141 List.iter 142 (fun (_, c) -> 143 Error.raise_warning 144 (Error.make "Duplicate %a in (children)." pp_children c 145 (Location_.location c))) 146 rest; 147 ( children_indexes, 148 (i, entry) :: indexed_content, 149 unindexed_content )) 150 (children_indexes, [], []) contents 151 in 152 List.iter 153 (fun (_, c) -> 154 Error.raise_warning 155 (Error.make "%a in (children) does not correspond to anything." 156 pp_children c (Location_.location c))) 157 children_indexes; 158 (indexed_content, unindexed_content) 159 in 160 let () = 161 match (children_order, unordered) with 162 | Some x, (_ :: _ as l) -> 163 Error.raise_warning 164 (Error.make "(children) doesn't include %a." 165 (Format.pp_print_list pp_content) 166 l (Location_.location x)) 167 | _ -> () 168 in 169 let ordered = 170 ordered 171 |> List.sort (fun (i, _) (j, _) -> (compare : int -> int -> int) i j) 172 |> List.map snd 173 in 174 let unordered = 175 List.sort (fun (_, x) (_, y) -> compare_entry x y) unordered 176 in 177 let contents = ordered @ unordered |> List.map snd in 178 { Tree.node = index; children = contents } 179 180let rec remove_common_root (v : t) = 181 match v with 182 | { Tree.children = [ v ]; node = { kind = Dir; _ } } -> remove_common_root v 183 | _ -> v 184 185let lang ~pages ~modules ~implementations = 186 let dir = In_progress.empty_t None in 187 List.iter (In_progress.add_page dir) pages; 188 List.iter (In_progress.add_module dir) modules; 189 List.iter (In_progress.add_implementation dir) implementations; 190 t_of_in_progress dir |> remove_common_root