package chatoyant
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
OCaml-first LLM SDK with Melange-generated JavaScript
Install
dune-project
Dependency
Authors
Maintainers
Sources
chatoyant-v0.12.2.tbz
sha256=a885dcf4b3c6ede268e2027bedf6955a5c889f7ed01c40b719f8369655957d47
sha512=0bb8dfa12157ba2e482927717c2242c1ea914dce1427801e405987811550afbd6d6b11f07d1e1379259360d17f4ca43ff81963bf407cddb7bedd0dfbb93a55ee
doc/src/chatoyant.schema/json_schema_resolver.ml.html
Source file json_schema_resolver.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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313module Json = Chatoyant_runtime.Json module Pointer = Json_schema_pointer type target = { uri : string; base_uri : string; schema : Json.t } type resource = { uri : string; schema : Json.t } type t = { root : Json.t; root_base_uri : string; resources : (string * Json.t) list; anchors : (string * Json.t) list; dynamic_anchors : (string * Json.t) list; } let root registry = registry.root let root_base_uri registry = registry.root_base_uri let has_scheme uri = match String.index_opt uri ':' with | None -> false | Some index -> index > 0 && let rec loop i = if i >= index then true else match uri.[i] with | 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '+' | '-' | '.' -> loop (i + 1) | _ -> false in loop 0 let split_document uri = fst (Pointer.split_uri_fragment uri) let normalize_path path = let absolute = String.length path > 0 && path.[0] = '/' in let trailing_slash = String.length path > 1 && path.[String.length path - 1] = '/' in let parts = path |> String.split_on_char '/' |> List.fold_left (fun acc part -> match part with | "" | "." -> acc | ".." -> ( match acc with [] -> [] | _ :: rest -> rest) | value -> value :: acc) [] |> List.rev in let normalized = (if absolute then "/" else "") ^ String.concat "/" parts in if trailing_slash && normalized <> "/" then normalized ^ "/" else normalized let uri = match String.index_opt uri ':' with | None -> None | Some colon -> if colon + 2 < String.length uri && uri.[colon + 1] = '/' && uri.[colon + 2] = '/' then let start = colon + 3 in let stop = match String.index_from_opt uri start '/' with | Some index -> index | None -> String.length uri in Some ( String.sub uri 0 colon, String.sub uri start (stop - start), if stop < String.length uri then String.sub uri stop (String.length uri - stop) else "/" ) else None let directory document = match String.rindex_opt document '/' with | None -> "" | Some index -> String.sub document 0 (index + 1) let resolve_uri ~base_uri reference = if reference = "" then split_document base_uri else if has_scheme reference then reference else let base_document = split_document base_uri in if String.length reference > 0 && reference.[0] = '#' then base_document ^ reference else if String.length reference > 0 && reference.[0] = '/' then match scheme_authority base_document with | Some (scheme, , _) -> scheme ^ "://" ^ authority ^ normalize_path reference | None -> normalize_path reference else match scheme_authority base_document with | Some (scheme, , path) -> let combined = normalize_path (directory path ^ reference) in scheme ^ "://" ^ authority ^ combined | None -> normalize_path (directory base_document ^ reference) let without_fragment uri = split_document uri let string_ends_with value suffix = let value_len = String.length value in let suffix_len = String.length suffix in suffix_len <= value_len && String.sub value (value_len - suffix_len) suffix_len = suffix let json_string_field name = function | Json.Object fields -> Option.bind (List.assoc_opt name fields) Json.as_string | _ -> None let is_schema_keyword name = match name with | "additionalProperties" | "unevaluatedProperties" | "propertyNames" | "items" | "contains" | "unevaluatedItems" | "not" | "if" | "then" | "else" -> true | _ -> false let is_schema_array_keyword name = match name with | "prefixItems" | "allOf" | "anyOf" | "oneOf" -> true | _ -> false let object_values = function | Json.Object fields -> List.map snd fields | _ -> [] let array_values = function Json.Array values -> values | _ -> [] let add_unique key value entries = if List.mem_assoc key entries then entries else (key, value) :: entries let merge_unique entries additions = List.fold_left (fun acc (key, value) -> add_unique key value acc) entries additions let scan root_base root = let rec loop base schema (resources, anchors, dynamic_anchors) = match schema with | Json.Bool _ -> (resources, anchors, dynamic_anchors) | Json.Object fields -> let base = match json_string_field "$id" schema with | None -> base | Some id -> resolve_uri ~base_uri:base id |> without_fragment in let resources = add_unique base schema resources in let anchors = match json_string_field "$anchor" schema with | None -> anchors | Some anchor -> add_unique (base ^ "#" ^ anchor) schema anchors in let dynamic_anchors = match json_string_field "$dynamicAnchor" schema with | None -> dynamic_anchors | Some anchor -> add_unique (base ^ "#" ^ anchor) schema dynamic_anchors in List.fold_left (fun acc (name, value) -> if is_schema_keyword name then match value with | Json.Bool _ | Json.Object _ -> loop base value acc | Json.Array _ | Json.Float _ | Json.String _ | Json.Null -> acc else if name = "$defs" || name = "definitions" || name = "properties" || name = "patternProperties" || name = "dependentSchemas" then List.fold_left (fun acc value -> loop base value acc) acc (object_values value) else if is_schema_array_keyword name then List.fold_left (fun acc value -> loop base value acc) acc (array_values value) else acc) (resources, anchors, dynamic_anchors) fields | _ -> (resources, anchors, dynamic_anchors) in loop root_base root ([], [], []) let scan_resource ~retrieval_uri schema (resources, anchors, dynamic_anchors) = let base_uri = match json_string_field "$id" schema with | None -> without_fragment retrieval_uri | Some id -> resolve_uri ~base_uri:retrieval_uri id |> without_fragment in let scanned_resources, scanned_anchors, scanned_dynamic_anchors = scan base_uri schema in let resources = merge_unique resources scanned_resources in let anchors = merge_unique anchors scanned_anchors in let dynamic_anchors = merge_unique dynamic_anchors scanned_dynamic_anchors in let resources = add_unique (without_fragment retrieval_uri) schema resources in (resources, anchors, dynamic_anchors, base_uri) let create ?(base_uri = "") ?(resources = []) root = let root_resources, root_anchors, root_dynamic_anchors, root_base_uri = scan_resource ~retrieval_uri:base_uri root ([], [], []) in let resources, anchors, dynamic_anchors = List.fold_left (fun (resources, anchors, dynamic_anchors) resource -> let scanned_resources, scanned_anchors, scanned_dynamic_anchors, _ = scan_resource ~retrieval_uri:resource.uri resource.schema (resources, anchors, dynamic_anchors) in (scanned_resources, scanned_anchors, scanned_dynamic_anchors)) (root_resources, root_anchors, root_dynamic_anchors) resources in let resources = add_unique "https://json-schema.org/draft/2020-12/schema" (Json.Bool true) resources in { root; root_base_uri; resources = List.rev resources; anchors = List.rev anchors; dynamic_anchors = List.rev dynamic_anchors; } let child_base_uri _registry ~base_uri schema = match json_string_field "$id" schema with | None -> base_uri | Some id -> let resolved = resolve_uri ~base_uri id |> without_fragment in let id_document = without_fragment id in if base_uri <> "" && (base_uri = resolved || (not (has_scheme id_document)) && string_ends_with base_uri id_document) then base_uri else resolved let resource registry document = if document = "" then Some registry.root else List.assoc_opt document registry.resources let resolve registry ~base_uri reference = let absolute = resolve_uri ~base_uri reference in let document, fragment = Pointer.split_uri_fragment absolute in let document = if document = "" then split_document base_uri else document in match Pointer.parse_fragment fragment with | Pointer.Empty -> ( match resource registry document with | None -> None | Some schema -> Some { uri = document; base_uri = document; schema }) | Pointer.Pointer tokens -> ( match resource registry document with | None -> None | Some schema -> ( match Pointer.resolve_pointer schema tokens with | None -> None | Some schema -> Some { uri = document ^ "#" ^ Pointer.pointer_to_string tokens; base_uri = document; schema; })) | Pointer.Anchor anchor -> ( match List.assoc_opt (document ^ "#" ^ anchor) registry.anchors with | Some schema -> Some { uri = document ^ "#" ^ anchor; base_uri = document; schema } | None -> ( match List.assoc_opt (document ^ "#" ^ anchor) registry.dynamic_anchors with | Some schema -> Some { uri = document ^ "#" ^ anchor; base_uri = document; schema } | None -> None)) let dynamic_anchors_for_resource registry base_uri = let document = without_fragment base_uri in registry.dynamic_anchors |> List.filter_map (fun (uri, schema) -> let document', fragment = Pointer.split_uri_fragment uri in match Pointer.parse_fragment fragment with | Pointer.Anchor anchor when document' = document -> Some (anchor, { uri; base_uri = document; schema }) | _ -> None) let resolve_dynamic registry ~base_uri ~dynamic_scope reference = let absolute = resolve_uri ~base_uri reference in let _, fragment = Pointer.split_uri_fragment absolute in match Pointer.parse_fragment fragment with | Pointer.Anchor anchor -> ( let static = resolve registry ~base_uri reference in let static_is_dynamic = match static with | None -> false | Some target -> ( match json_string_field "$dynamicAnchor" target.schema with | Some dynamic_anchor when dynamic_anchor = anchor -> true | _ -> false) in if not static_is_dynamic then static else match List.assoc_opt anchor dynamic_scope with | Some target -> Some target | None -> resolve registry ~base_uri reference) | _ -> resolve registry ~base_uri reference
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>