this repo has no description
1(** Page-level orchestration for x-ocaml cells.
2
3 A page contains a collection of {!Cell.t} values arranged in document
4 order. This module manages:
5
6 - {b Cell registry}: looking up cells by numeric id or by [data-id].
7 - {b Execution chain}: linking cells into a linear predecessor chain so
8 that running a cell automatically runs its prerequisites.
9 - {b Test linking}: connecting {!Cell.Test} cells to their target
10 {!Cell.Exercise} cells, either positionally (nearest preceding exercise)
11 or explicitly via [data-for] / [data-id] attributes. After an exercise
12 cell completes, its linked test cells run automatically.
13 - {b Auto-run}: triggering cells whose [run-on] is ["load"] once all
14 cells have been registered.
15 - {b Backend message routing}: dispatching responses from the backend to
16 the correct cell.
17
18 {2 Typical lifecycle}
19
20 {[
21 let page = Page.create ~backend () in
22 (* WebComponent connectedCallback fires for each <x-ocaml>: *)
23 let _cell = Page.register page element in
24 (* After all cells registered, auto-run triggers. *)
25 ]}
26
27 {2 Test linking}
28
29 When a {!Cell.Test} cell is registered, the page links it to an exercise:
30
31 - If the test has [data-for="some-id"], it links to the exercise cell
32 whose [data-id="some-id"].
33 - Otherwise it links to the nearest preceding {!Cell.Exercise}.
34
35 After an exercise cell's run completes, all test cells linked to it are
36 triggered automatically. If a test cell is registered after its linked
37 exercise has already completed, the test is triggered immediately upon
38 registration.
39
40 {2 Universe discovery}
41
42 During creation, the page reads
43 [<meta name="x-ocaml-packages" content="pkg1,pkg2,...">] from the document
44 head. If present, each package name is used to register dynamic CMIs with
45 the merlin worker so that type information (completions, type-on-hover,
46 error checking) is available for those packages.
47
48 For each package [pkg], CMIs are expected at [{base_url}/{pkg}/] where
49 [base_url] defaults to ["./cmis/"] and can be overridden with
50 [<meta name="x-ocaml-cmis-url" content="...">]. The toplevel module is
51 assumed to be [{Pkg}] (capitalised) with sub-modules prefixed [{pkg}__].
52
53 {b Note:} For the toplevel {e evaluator} to have access to the packages,
54 their JavaScript bundles must be loaded separately via the [src-load]
55 attribute on the [<script>] tag. Universe discovery only configures merlin. *)
56
57type t
58(** Mutable page-level state: cell registry, backend handle, and page-wide
59 configuration. *)
60
61val create :
62 backend:Backend.t ->
63 ?extra_style:Jstr.t ->
64 ?inline_style:Jstr.t ->
65 ?default_run_on:string ->
66 ?format_config:string ->
67 unit ->
68 t
69(** Create a new page and initialise the backend.
70
71 Sends [Setup] to the backend, registers a message handler that routes
72 responses to the appropriate cell, and reads
73 [<meta name="x-ocaml-packages">] and [<meta name="x-ocaml-cmis-url">]
74 from the document to configure merlin's dynamic CMI loading.
75
76 @param backend The evaluation/formatting backend.
77 @param extra_style Default stylesheet URL applied to every cell.
78 @param inline_style Default inline CSS for every cell's [:host] selector.
79 @param default_run_on Default [run-on] value for cells that don't specify
80 their own (["load"] or ["click"]). Defaults to ["load"].
81 @param format_config OCamlformat configuration string. If provided,
82 sent to the backend as [Format_config]. *)
83
84(** {1 Cell registration} *)
85
86val register : t -> Webcomponent.t -> Cell.t
87(** [register page element] creates and registers a new cell from the
88 given custom element.
89
90 Reads the following attributes from [element]:
91
92 - [mode]: cell mode (["interactive"], ["exercise"], ["test"], ["hidden"]).
93 Defaults to ["interactive"].
94 - [data-id]: makes this cell addressable by name for test linking.
95 - [data-for]: links a test cell to an exercise cell by [data-id].
96 - [data-env]: reserved for future environment scoping.
97 - [data-filename]: filename for merlin and error reporting.
98 - [data-merlin]: ["false"] to disable merlin for this cell.
99 - [run-on]: per-cell override of the default run-on behaviour.
100
101 After creation, the cell is:
102 + Added to the registry.
103 + Linked into the execution chain (predecessor set to the previous cell).
104 + If it is a {!Cell.Test}, linked to its target exercise cell. If the
105 target exercise has already completed, the test is triggered immediately.
106 + Started (initial source loaded from element [textContent]).
107 + If all cells so far are loadable, the last cell is auto-run. *)
108
109(** {1 Reset} *)
110
111val reset_all : t -> unit
112(** [reset_all page] terminates the current worker, creates a fresh one,
113 replays initialisation messages (Setup, Format_config, Add_cmis), and
114 resets every cell to {!Cell.Not_run}. The user must re-run cells from
115 the top since the new worker has no accumulated state. *)
116
117(** {1 Lookups} *)
118
119val find_by_id : t -> int -> Cell.t
120(** [find_by_id page id] returns the cell with numeric id [id].
121 @raise Not_found if no such cell exists. *)
122
123val find_by_cell_id : t -> string -> Cell.t option
124(** [find_by_cell_id page name] returns the cell whose [data-id] is [name],
125 if any. *)
126
127val cells : t -> Cell.t list
128(** All registered cells in document order (first cell at the head). *)