let current_script = Brr.El.of_jv (Jv.get (Brr.Document.to_jv Brr.G.document) "currentScript") let current_attribute attr = Brr.El.at (Jstr.of_string attr) current_script let read_meta name = let doc = Brr.Document.to_jv Brr.G.document in let selector = Jstr.of_string ("meta[name=\"" ^ name ^ "\"]") in let result = Jv.call doc "querySelector" [| Jv.of_jstr selector |] in if Jv.is_none result then None else let content = Jv.call result "getAttribute" [| Jv.of_string "content" |] in if Jv.is_none content then None else Some (Jv.to_string content) let () = let extra_load = match current_attribute "src-load" with | None -> None | Some url -> Some (Jstr.to_string url) in let backend_name = match current_attribute "backend" with | Some name -> Jstr.to_string name | None -> match read_meta "x-ocaml-backend" with | Some name -> name | None -> (* Infer backend from universe: if a universe is configured, use jtw *) match read_meta "x-ocaml-universe" with | Some _ -> "jtw" | None -> "builtin" in let findlib_requires = match read_meta "x-ocaml-packages" with | None -> None | Some s -> let pkgs = List.filter (fun s -> s <> "") (List.map String.trim (String.split_on_char ',' s)) in if pkgs = [] then None else Some pkgs in let resolve_url relative = let url_ctor = Jv.get Jv.global "URL" in let loc = Jv.get (Jv.get Jv.global "window") "location" in let href = Jv.to_string (Jv.get loc "href") in let url_obj = Jv.new' url_ctor [| Jv.of_string relative; Jv.of_string href |] in Jv.to_string (Jv.get url_obj "href") in let findlib_index_url = match read_meta "x-ocaml-universe" with | None -> None | Some base -> let base = if String.length base > 0 && base.[String.length base - 1] = '/' then base else base ^ "/" in Some (resolve_url (base ^ "findlib_index.json")) in let sync_fetch_text url = let xhr = Jv.new' (Jv.get Jv.global "XMLHttpRequest") [||] in Jv.call xhr "open" [| Jv.of_string "GET"; Jv.of_string url; Jv.of_bool false |] |> ignore; (try Jv.call xhr "send" [||] |> ignore with _ -> ()); let status = Jv.to_int (Jv.get xhr "status") in if status = 200 then Some (Jv.to_string (Jv.get xhr "responseText")) else None in let findlib_index_json = match findlib_index_url with | None -> None | Some url -> match sync_fetch_text url with | None -> None | Some text -> (try Some (Jv.call (Jv.get Jv.global "JSON") "parse" [| Jv.of_string text |]) with _ -> None) in let findlib_index_base_dir = match findlib_index_url with | None -> "" | Some fi_url -> match String.rindex_opt fi_url '/' with | Some i -> String.sub fi_url 0 (i + 1) | None -> fi_url in let worker_url_from_findlib_index = match findlib_index_json with | None -> None | Some json -> let compiler = Jv.get json "compiler" in if Jv.is_none compiler || Jv.is_undefined compiler then None else let worker_url = Jv.get compiler "worker_url" in if not (Jv.is_none worker_url || Jv.is_undefined worker_url) then Some (findlib_index_base_dir ^ Jv.to_string worker_url) else try let version = Jv.to_string (Jv.get compiler "version") in let content_hash = Jv.to_string (Jv.get compiler "content_hash") in Some (findlib_index_base_dir ^ "../../../compiler/" ^ version ^ "/" ^ content_hash ^ "/worker.js") with _ -> None in let worker_url = match read_meta "x-ocaml-worker" with | Some url -> Some url | None -> match worker_url_from_findlib_index with | Some url -> Some url | None -> match current_attribute "src-worker" with | None -> if backend_name = "builtin" then None else Some "" | Some url -> Some (Jstr.to_string url) in match worker_url with | None -> (* No worker URL available — x-ocaml elements on this page are inert (e.g. code blocks on non-interactive pages due to resource leak). *) () | Some worker_url -> let backend = Backend.make ~backend:backend_name ?extra_load ?findlib_requires ?findlib_index:findlib_index_url worker_url in let format_config = match current_attribute "x-ocamlformat" with | None -> None | Some conf -> Some (Jstr.to_string conf) in let extra_style = current_attribute "src-style" in let inline_style = current_attribute "inline-style" in let default_run_on = current_attribute "run-on" |> Option.map Jstr.to_string in let page = Page.create ~backend ?extra_style ?inline_style ?default_run_on ?format_config () in let elt_name = match current_attribute "elt-name" with | None -> Jstr.of_string "x-ocaml" | Some name -> name in ignore @@ Webcomponent.define elt_name @@ fun this -> let _cell = Page.register page this in ()