this repo has no description
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 ()