OCaml HTML5 parser/serialiser based on Python's JustHTML
1(** Registry for HTML5 conformance checkers.
2
3 This module provides a dynamic registry for managing collections of
4 checkers. It enables:
5
6 - {b Registration}: Add checkers under descriptive names
7 - {b Discovery}: Retrieve checkers by name or list all available ones
8 - {b Lifecycle management}: Register and unregister checkers at runtime
9 - {b Defaults}: Access a pre-configured set of built-in checkers
10
11 {2 Design Rationale}
12
13 The registry pattern separates checker implementation from checker usage.
14 Applications can:
15
16 1. Query available checkers to present options to users
17 2. Select specific checkers based on validation requirements
18 3. Add custom checkers without modifying library code
19 4. Share checker configurations across validation runs
20
21 {2 Usage Pattern}
22
23 {[
24 (* Start with default checkers *)
25 let reg = default () in
26
27 (* Add a custom checker *)
28 let my_checker = (module MyChecker : Checker.S) in
29 register reg "my-custom-check" my_checker;
30
31 (* List all available checkers *)
32 let names = list_names reg in
33 List.iter (Printf.printf "Available: %s\n") names;
34
35 (* Retrieve a specific checker *)
36 match get reg "my-custom-check" with
37 | Some checker -> (* Use the checker *)
38 | None -> (* Not found *)
39
40 (* Get all checkers for validation *)
41 let all_checkers = all reg in
42 (* Pass to dom_walker *)
43 ]}
44
45 {2 Thread Safety}
46
47 This registry is not thread-safe. If shared across threads, external
48 synchronization is required. *)
49
50(** {1 Types} *)
51
52(** The type of a checker registry.
53
54 This is an opaque type representing a mutable collection of named
55 checkers. Internally implemented as a hash table for efficient lookups. *)
56type t
57
58(** {1 Creation} *)
59
60val create : unit -> t
61(** [create ()] creates a new empty checker registry.
62
63 Use this when you want to build a custom set of checkers from scratch,
64 without any defaults. *)
65
66val default : unit -> t
67(** [default ()] creates a registry with built-in checkers.
68
69 The default registry is initially empty but serves as a starting point
70 for adding standard validation checkers in future phases.
71
72 Built-in checkers will include:
73 - Document structure validation
74 - Attribute validation
75 - Content model checking
76 - Accessibility checks
77
78 Note: In Phase 1, the default registry is empty. Built-in checkers
79 will be added in subsequent phases. *)
80
81(** {1 Registration} *)
82
83val register : t -> string -> Checker.t -> unit
84(** [register registry name checker] adds a checker to the registry.
85
86 @param registry The registry to add to
87 @param name A unique identifier for the checker (e.g., "obsolete-elements",
88 "required-attributes")
89 @param checker The checker implementation
90
91 If a checker with the same name already exists, it is replaced.
92
93 {b Example:}
94 {[
95 let reg = create () in
96 let checker = (module MyChecker : Checker.S) in
97 register reg "my-check" checker
98 ]} *)
99
100val unregister : t -> string -> unit
101(** [unregister registry name] removes a checker from the registry.
102
103 @param registry The registry to remove from
104 @param name The checker name
105
106 If no checker with the given name exists, this is a no-op. *)
107
108(** {1 Retrieval} *)
109
110val get : t -> string -> Checker.t option
111(** [get registry name] retrieves a checker by name.
112
113 @param registry The registry to search
114 @param name The checker name
115 @return [Some checker] if found, [None] otherwise
116
117 {b Example:}
118 {[
119 match get reg "obsolete-elements" with
120 | Some checker -> (* Use checker *)
121 | None -> (* Checker not registered *)
122 ]} *)
123
124val list_names : t -> string list
125(** [list_names registry] returns all registered checker names.
126
127 @param registry The registry to query
128 @return A list of all checker names in arbitrary order
129
130 This is useful for:
131 - Displaying available checkers to users
132 - Debugging registry contents
133 - Iterating over specific subsets of checkers
134
135 {b Example:}
136 {[
137 let names = list_names reg in
138 Printf.printf "Available checkers: %s\n"
139 (String.concat ", " names)
140 ]} *)
141
142val all : t -> Checker.t list
143(** [all registry] returns all registered checkers.
144
145 @param registry The registry to query
146 @return A list of all checkers in arbitrary order
147
148 This is the primary way to retrieve checkers for validation.
149 Pass the result to {!Dom_walker.walk_all} to run all registered
150 checkers on a DOM tree.
151
152 {b Example:}
153 {[
154 let checkers = all reg in
155 Dom_walker.walk_all checkers collector dom
156 ]} *)