···22open Types
33module Id = Odoc_model.Paths.Identifier
4455+type entry = Url.t option * Inline.one
66+57module Toc : sig
66- type t
88+ type t = entry Tree.t
79810 val of_page_hierarchy : Odoc_index.Page_hierarchy.t -> t
911···11131214 val to_block : prune:bool -> Url.Path.t -> t -> Block.t
1315end = struct
1414- type t = (Url.t option * Inline.one) Tree.t
1616+ type t = entry Tree.t
15171618 let of_page_hierarchy (dir : Odoc_index.Page_hierarchy.t) : t =
1719 let f index =
+9-1
src/document/sidebar.mli
···11-type t
11+open Odoc_utils
22+open Types
33+44+type entry = Url.t option * Inline.one
55+66+type pages = { name : string; pages : entry Tree.t }
77+type library = { name : string; units : entry Tree.t list }
88+99+type t = { pages : pages list; libraries : library list }
210311val of_lang : Odoc_index.t -> t
412
+4
src/html/generator.ml
···590590let doc ~config ~xref_base_uri b =
591591 let resolve = Link.Base xref_base_uri in
592592 block ~config ~resolve b
593593+594594+let inline ~config ~xref_base_uri b =
595595+ let resolve = Link.Base xref_base_uri in
596596+ inline ~config ~resolve b
···476476 Antichain.check (lib_roots |> List.map ~f:snd) ~opt:"-L" >>= fun () ->
477477 Indexing.compile marshall ~output ~warnings_options ~occurrences ~lib_roots
478478 ~page_roots ~inputs_in_file ~odocls:inputs
479479+479480 let cmd =
480481 let dst =
481482 let doc =
···542543 in the given directories."
543544 in
544545 Term.info "compile-index" ~docs ~doc
546546+end
547547+548548+module Sidebar = struct
549549+ open Or_error
550550+551551+ let output_file ~dst marshall =
552552+ match (dst, marshall) with
553553+ | Some file, `JSON when not (Fpath.has_ext "json" (Fpath.v file)) ->
554554+ Error
555555+ (`Msg
556556+ "When generating a json index, the output must have a .json file \
557557+ extension")
558558+ | Some file, `Marshall when not (Fpath.has_ext "odoc-index" (Fpath.v file))
559559+ ->
560560+ Error
561561+ (`Msg
562562+ "When generating a binary index, the output must have a \
563563+ .odoc-sidebar file extension")
564564+ | Some file, _ -> Ok (Fs.File.of_string file)
565565+ | None, `JSON -> Ok (Fs.File.of_string "sidebar.json")
566566+ | None, `Marshall -> Ok (Fs.File.of_string "sidebar.odoc-sidebar")
567567+568568+ let generate dst json warnings_options input =
569569+ let marshall = if json then `JSON else `Marshall in
570570+ output_file ~dst marshall >>= fun output ->
571571+ Sidebar.generate ~marshall ~output ~warnings_options ~index:input
572572+573573+ let cmd =
574574+ let dst =
575575+ let doc =
576576+ "Output file path. Non-existing intermediate directories are created. \
577577+ Defaults to sidebar.odoc-sidebar, or sidebar.json if --json is \
578578+ passed."
579579+ in
580580+ Arg.(
581581+ value & opt (some string) None & info ~docs ~docv:"PATH" ~doc [ "o" ])
582582+ in
583583+ let json =
584584+ let doc = "whether to output a json file, or a binary .odoc-index file" in
585585+ Arg.(value & flag & info ~doc [ "json" ])
586586+ in
587587+ let inputs =
588588+ let doc = ".odoc-index file to generate a value from" in
589589+ Arg.(
590590+ required & pos 0 (some convert_fpath) None & info ~doc ~docv:"FILE" [])
591591+ in
592592+ Term.(
593593+ const handle_error
594594+ $ (const generate $ dst $ json $ warnings_options $ inputs))
595595+596596+ let info ~docs =
597597+ let doc = "Generate a sidebar from an index file." in
598598+ Term.info "sidebar-generate" ~docs ~doc
545599end
546600547601module Support_files_command = struct
···15751629 Support_files_command.(cmd, info ~docs:section_pipeline);
15761630 Compile_impl.(cmd, info ~docs:section_pipeline);
15771631 Indexing.(cmd, info ~docs:section_pipeline);
16321632+ Sidebar.(cmd, info ~docs:section_pipeline);
15781633 Odoc_manpage.generate ~docs:section_generators;
15791634 Odoc_latex.generate ~docs:section_generators;
15801635 Odoc_html_url.(cmd, info ~docs:section_support);
···5656val load_index : Fs.File.t -> (Odoc_index.t, [> msg ]) result
5757(** Load a [.odoc-index] file. *)
58585959+val save_sidebar : Fs.File.t -> Odoc_document.Sidebar.t -> unit
6060+6161+val load_sidebar : Fs.File.t -> (Odoc_document.Sidebar.t, [> msg ]) result
6262+(** Load a [.odoc-index] file. *)
6363+5964val save_asset : Fpath.t -> warnings:Error.t list -> Lang.Asset.t -> unit
+60
src/odoc/sidebar.ml
···11+open Or_error
22+open Odoc_utils
33+44+let toc_to_json ((url, inline) : Odoc_document.Sidebar.entry) : Json.json =
55+ let config =
66+ Odoc_html.Config.v ~semantic_uris:true ~indent:true ~flat:false
77+ ~open_details:false ~as_json:true ~remap:[] ()
88+ in
99+ let url =
1010+ match url with
1111+ | None -> `Null
1212+ | Some url ->
1313+ let href =
1414+ Odoc_html.Link.href ~config ~resolve:(Odoc_html.Link.Base "") url
1515+ in
1616+ `String href
1717+ in
1818+ let inline =
1919+ let inline =
2020+ Odoc_html.Generator.inline ~config ~xref_base_uri:"" [ inline ]
2121+ in
2222+ let inline =
2323+ String.concat ""
2424+ @@ List.map (Format.asprintf "%a" (Tyxml.Html.pp_elt ())) inline
2525+ in
2626+ `String inline
2727+ in
2828+ `Object [ ("url", url); ("content", inline) ]
2929+3030+let pages_to_json ({ name; pages } : Odoc_document.Sidebar.pages) =
3131+ `Object [ ("name", `String name); ("pages", Tree.to_json toc_to_json pages) ]
3232+3333+let libs_to_json ({ name; units } : Odoc_document.Sidebar.library) =
3434+ `Object
3535+ [
3636+ ("name", `String name);
3737+ ("modules", `Array (List.map (Tree.to_json toc_to_json) units));
3838+ ]
3939+4040+let sidebar_to_json ({ pages; libraries } : Odoc_document.Sidebar.t) =
4141+ let pages = List.map pages_to_json pages in
4242+ let libraries = List.map libs_to_json libraries in
4343+ `Object [ ("pages", `Array pages); ("libraries", `Array libraries) ]
4444+4545+let compile_to_json ~output sidebar =
4646+ let json = sidebar_to_json sidebar in
4747+ let text = Json.to_string json in
4848+ let output_channel =
4949+ Fs.Directory.mkdir_p (Fs.File.dirname output);
5050+ open_out_bin (Fs.File.to_string output)
5151+ in
5252+ let output = Format.formatter_of_out_channel output_channel in
5353+ Format.fprintf output "%s" text
5454+5555+let generate ~marshall ~output ~warnings_options:_ ~index =
5656+ Odoc_file.load_index index >>= fun index ->
5757+ let sidebar = Odoc_document.Sidebar.of_lang index in
5858+ match marshall with
5959+ | `JSON -> Ok (compile_to_json ~output sidebar)
6060+ | `Marshall -> Ok (Odoc_file.save_sidebar output sidebar)
+7
src/utils/tree.ml
···99 val fold_left : f:('acc -> 'a -> 'acc) -> 'acc -> 'a t -> 'acc
1010 val iter : f:('a -> unit) -> 'a t -> unit
1111 val map : f:('a -> 'b) -> 'a t -> 'b t
1212+ val to_json : ('a -> Json.json) -> 'a t -> Json.json
1213end
13141415type 'a t = 'a tree
1616+1717+let rec to_json json_of { node; children } : Json.json =
1818+ `Object [ ("node", json_of node); ("children", to_json_f json_of children) ]
1919+2020+and to_json_f json_of f = `Array (List.map (to_json json_of) f)
15211622let leaf node = { node; children = [] }
1723···5056 let iter = iter_forest
5157 let map = map_forest
5258 let filter_map = filter_map_forest
5959+ let to_json = to_json_f
5360end
+1
src/utils/tree.mli
···99 val fold_left : f:('acc -> 'a -> 'acc) -> 'acc -> 'a t -> 'acc
1010 val iter : f:('a -> unit) -> 'a t -> unit
1111 val map : f:('a -> 'b) -> 'a t -> 'b t
1212+ val to_json : ('a -> Json.json) -> 'a t -> Json.json
1213end
13141415include S with type 'a t = 'a tree