this repo has no description

Add resources and assets support for odoc JSON output

- odoc JSON output now includes resources (CSS/JS) and assets (binary files)
in the JSON schema, enabling extensions to contribute styling to docsites
- odoc-docsite parses and handles resources from JSON:
- Injects CSS/JS links into generated HTML pages
- Writes base64-decoded binary assets to output directory
- Copies extension support files from HTML output's extensions/ directory
- Fix resource path resolution to use proper relative paths from page to root

This enables odoc extension plugins (RFC, admonition, MSC, Mermaid, DOT) to
provide their CSS/JS resources when documentation is built via the JSON
pipeline and rendered with odoc-docsite.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+34 -6
+1 -1
src/html/dune
··· 5 5 (backend landmarks --auto)) 6 6 (instrumentation 7 7 (backend bisect_ppx)) 8 - (libraries odoc_model odoc_document tyxml)) 8 + (libraries odoc_model odoc_document tyxml base64))
+2 -1
src/html/generator.ml
··· 680 680 in 681 681 Html_fragment_json.make ~config 682 682 ~preamble:(preamble :> any Html.elt list) 683 - ~header ~breadcrumbs ~toc ~url ~uses_katex ~source_anchor content 683 + ~header ~breadcrumbs ~toc ~url ~uses_katex ~source_anchor 684 + ~resources ~assets content 684 685 subpages 685 686 else 686 687 Html_page.make ~sidebar ~config ~header:(header @ preamble) ~toc
+25 -2
src/html/html_fragment_json.ml
··· 10 10 let htmlpp = Html.pp_elt ~indent:(Config.indent config) () in 11 11 String.concat ~sep:"" (List.map (Format.asprintf "%a" htmlpp) h) 12 12 13 + let json_of_resource (r : Odoc_extension_registry.resource) : Json.json = 14 + match r with 15 + | Js_url url -> `Object [ ("type", `String "js_url"); ("value", `String url) ] 16 + | Css_url url -> `Object [ ("type", `String "css_url"); ("value", `String url) ] 17 + | Js_inline code -> `Object [ ("type", `String "js_inline"); ("value", `String code) ] 18 + | Css_inline code -> `Object [ ("type", `String "css_inline"); ("value", `String code) ] 19 + 20 + let json_of_resources resources : Json.json = 21 + `Array (List.map json_of_resource resources) 22 + 23 + let json_of_asset (a : Odoc_extension_registry.asset) : Json.json = 24 + (* For JSON output, we encode binary content as base64 *) 25 + let content_b64 = Base64.encode_string (Bytes.to_string a.asset_content) in 26 + `Object [ 27 + ("filename", `String a.asset_filename); 28 + ("content_base64", `String content_b64); 29 + ] 30 + 31 + let json_of_assets assets : Json.json = 32 + `Array (List.map json_of_asset assets) 33 + 13 34 let json_of_breadcrumbs config (breadcrumbs : Types.breadcrumbs) : Json.json = 14 35 let breadcrumb (b : Types.breadcrumb) = 15 36 `Object ··· 42 63 | Some sidebar -> `String (json_of_html config sidebar) 43 64 44 65 let make ~config ~preamble ~url ~breadcrumbs ~toc ~uses_katex ~source_anchor 45 - ~header content children = 66 + ~resources ~assets ~header content children = 46 67 let filename = Link.Path.as_filename ~config url in 47 68 let filename = Fpath.add_ext ".json" filename in 48 69 let json_to_string json = Json.to_string json in ··· 62 83 ("source_anchor", source_anchor); 63 84 ("preamble", `String (json_of_html config preamble)); 64 85 ("content", `String (json_of_html config content)); 86 + ("resources", json_of_resources resources); 87 + ("assets", json_of_assets assets); 65 88 ])) 66 89 in 67 - { Odoc_document.Renderer.filename; content; children; path = url; assets = [] } 90 + { Odoc_document.Renderer.filename; content; children; path = url; assets } 68 91 69 92 let make_src ~config ~url ~breadcrumbs ~sidebar ~header content = 70 93 let filename = Link.Path.as_filename ~config url in
+2
src/html/html_fragment_json.mli
··· 8 8 toc:Types.toc list -> 9 9 uses_katex:bool -> 10 10 source_anchor:string option -> 11 + resources:Odoc_extension_registry.resource list -> 12 + assets:Odoc_extension_registry.asset list -> 11 13 header:Html_types.flow5_without_header_footer Html.elt list -> 12 14 Html_types.div_content Html.elt list -> 13 15 Odoc_document.Renderer.page list ->
+4 -2
src/html/html_page.ml
··· 189 189 List.concat_map 190 190 (function 191 191 | Js_url url -> 192 - [ Html.script ~a:[ Html.a_src url ] (Html.txt "") ] 192 + let resolved_url = file_uri support_uri url in 193 + [ Html.script ~a:[ Html.a_src resolved_url ] (Html.txt "") ] 193 194 | Css_url url -> 194 - [ Html.link ~rel:[ `Stylesheet ] ~href:url () ] 195 + let resolved_url = file_uri support_uri url in 196 + [ Html.link ~rel:[ `Stylesheet ] ~href:resolved_url () ] 195 197 | Js_inline code -> 196 198 [ Html.script (Html.cdata_script code) ] 197 199 | Css_inline code ->