this repo has no description
at main 161 lines 5.1 kB view raw
1let current_script = 2 Brr.El.of_jv (Jv.get (Brr.Document.to_jv Brr.G.document) "currentScript") 3 4let current_attribute attr = Brr.El.at (Jstr.of_string attr) current_script 5 6let read_meta name = 7 let doc = Brr.Document.to_jv Brr.G.document in 8 let selector = Jstr.of_string ("meta[name=\"" ^ name ^ "\"]") in 9 let result = Jv.call doc "querySelector" [| Jv.of_jstr selector |] in 10 if Jv.is_none result then None 11 else 12 let content = Jv.call result "getAttribute" [| Jv.of_string "content" |] in 13 if Jv.is_none content then None 14 else Some (Jv.to_string content) 15 16let () = 17 let extra_load = 18 match current_attribute "src-load" with 19 | None -> None 20 | Some url -> Some (Jstr.to_string url) 21 in 22 23 let backend_name = 24 match current_attribute "backend" with 25 | Some name -> Jstr.to_string name 26 | None -> 27 match read_meta "x-ocaml-backend" with 28 | Some name -> name 29 | None -> 30 (* Infer backend from universe: if a universe is configured, use jtw *) 31 match read_meta "x-ocaml-universe" with 32 | Some _ -> "jtw" 33 | None -> "builtin" 34 in 35 36 let findlib_requires = 37 match read_meta "x-ocaml-packages" with 38 | None -> None 39 | Some s -> 40 let pkgs = List.filter (fun s -> s <> "") 41 (List.map String.trim (String.split_on_char ',' s)) in 42 if pkgs = [] then None else Some pkgs 43 in 44 45 let resolve_url relative = 46 let url_ctor = Jv.get Jv.global "URL" in 47 let loc = Jv.get (Jv.get Jv.global "window") "location" in 48 let href = Jv.to_string (Jv.get loc "href") in 49 let url_obj = Jv.new' url_ctor [| Jv.of_string relative; Jv.of_string href |] in 50 Jv.to_string (Jv.get url_obj "href") 51 in 52 53 let findlib_index_url = 54 match read_meta "x-ocaml-universe" with 55 | None -> None 56 | Some base -> 57 let base = if String.length base > 0 && base.[String.length base - 1] = '/' 58 then base else base ^ "/" in 59 Some (resolve_url (base ^ "findlib_index.json")) 60 in 61 62 let sync_fetch_text url = 63 let xhr = Jv.new' (Jv.get Jv.global "XMLHttpRequest") [||] in 64 Jv.call xhr "open" [| Jv.of_string "GET"; Jv.of_string url; Jv.of_bool false |] |> ignore; 65 (try Jv.call xhr "send" [||] |> ignore with _ -> ()); 66 let status = Jv.to_int (Jv.get xhr "status") in 67 if status = 200 then Some (Jv.to_string (Jv.get xhr "responseText")) 68 else None 69 in 70 71 let findlib_index_json = 72 match findlib_index_url with 73 | None -> None 74 | Some url -> 75 match sync_fetch_text url with 76 | None -> None 77 | Some text -> 78 (try 79 Some (Jv.call (Jv.get Jv.global "JSON") "parse" [| Jv.of_string text |]) 80 with _ -> None) 81 in 82 83 let findlib_index_base_dir = 84 match findlib_index_url with 85 | None -> "" 86 | Some fi_url -> 87 match String.rindex_opt fi_url '/' with 88 | Some i -> String.sub fi_url 0 (i + 1) 89 | None -> fi_url 90 in 91 92 let worker_url_from_findlib_index = 93 match findlib_index_json with 94 | None -> None 95 | Some json -> 96 let compiler = Jv.get json "compiler" in 97 if Jv.is_none compiler || Jv.is_undefined compiler then None 98 else 99 let worker_url = Jv.get compiler "worker_url" in 100 if not (Jv.is_none worker_url || Jv.is_undefined worker_url) then 101 Some (findlib_index_base_dir ^ Jv.to_string worker_url) 102 else 103 try 104 let version = Jv.to_string (Jv.get compiler "version") in 105 let content_hash = Jv.to_string (Jv.get compiler "content_hash") in 106 Some (findlib_index_base_dir ^ "../../../compiler/" ^ version ^ "/" ^ content_hash ^ "/worker.js") 107 with _ -> None 108 in 109 110 let worker_url = 111 match read_meta "x-ocaml-worker" with 112 | Some url -> Some url 113 | None -> 114 match worker_url_from_findlib_index with 115 | Some url -> Some url 116 | None -> 117 match current_attribute "src-worker" with 118 | None -> 119 if backend_name = "builtin" then None 120 else Some "" 121 | Some url -> Some (Jstr.to_string url) 122 in 123 124 match worker_url with 125 | None -> 126 (* No worker URL available — x-ocaml elements on this page are inert 127 (e.g. code blocks on non-interactive pages due to resource leak). *) 128 () 129 | Some worker_url -> 130 131 let backend = Backend.make ~backend:backend_name ?extra_load ?findlib_requires 132 ?findlib_index:findlib_index_url worker_url 133 in 134 135 let format_config = 136 match current_attribute "x-ocamlformat" with 137 | None -> None 138 | Some conf -> Some (Jstr.to_string conf) 139 in 140 141 let extra_style = current_attribute "src-style" in 142 let inline_style = current_attribute "inline-style" in 143 144 let default_run_on = 145 current_attribute "run-on" |> Option.map Jstr.to_string 146 in 147 148 let page = 149 Page.create ~backend ?extra_style ?inline_style ?default_run_on 150 ?format_config () 151 in 152 153 let elt_name = 154 match current_attribute "elt-name" with 155 | None -> Jstr.of_string "x-ocaml" 156 | Some name -> name 157 in 158 159 ignore @@ Webcomponent.define elt_name @@ fun this -> 160 let _cell = Page.register page this in 161 ()