Source file inline_css.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
open! Core
open Js_of_ocaml
module Style_sheet = struct
class type t =
object
method replaceSync : Js.js_string Js.t -> unit Js.meth
end
let t : t Js.t Js.constr = Js.Unsafe.global##._CSSStyleSheet
let append : t Js.t -> unit =
Js.Unsafe.pure_js_expr
{js|
(function (style_sheet) {
// push doesn't work because this field is really weird.
document.adoptedStyleSheets =
Array.prototype.concat.apply(document.adoptedStyleSheets, [style_sheet]);
})
|js}
;;
end
let all_css = ref Reversed_list.[]
let global_style_sheet = ref None
let to_string () = !all_css |> Reversed_list.rev |> String.concat ~sep:"\n"
let print_for_testing =
let regex = Re.Str.regexp "_hash_\\([a-z0-9]+\\)*" in
fun () ->
to_string () |> Re.Str.global_replace regex "_hash_replaced_in_test" |> print_endline
;;
let install_in_dom () =
let style_sheet = new%js Style_sheet.t in
Style_sheet.append style_sheet;
style_sheet##replaceSync (Js.string (to_string ()));
global_style_sheet := Some style_sheet
;;
let maybe_update_in_dom () =
match !global_style_sheet with
| Some style_sheet -> style_sheet##replaceSync (Js.string (to_string ()))
| None -> ()
;;
let append a =
(all_css := Reversed_list.(a :: !all_css));
maybe_update_in_dom ()
;;
let () =
let ready_state =
Option.try_with (fun () -> Dom_html.document##.readyState |> Js.to_string)
in
match ready_state with
| Some ("interactive" | "complete") -> install_in_dom ()
| Some ("loading" | _) ->
let _id : Dom_html.event_listener_id =
Dom_html.addEventListenerWithOptions
~passive:Js._true
~capture:Js._false
~once:Js._true
Dom_html.window
Dom_html.Event.domContentLoaded
(Dom.handler (fun _ ->
install_in_dom ();
Js._true))
in
()
| None -> ()
;;
module Private = struct
let append = append
end