1use schemars::schema::{ArrayValidation, InstanceType, RootSchema, Schema, SchemaObject};
2use serde_json::Value;
3
4pub struct SettingsJsonSchemaParams<'a> {
5 pub language_names: &'a [String],
6 pub font_names: &'a [String],
7}
8
9impl<'a> SettingsJsonSchemaParams<'a> {
10 pub fn font_family_schema(&self) -> Schema {
11 let available_fonts: Vec<_> = self.font_names.iter().cloned().map(Value::String).collect();
12
13 SchemaObject {
14 instance_type: Some(InstanceType::String.into()),
15 enum_values: Some(available_fonts),
16 ..Default::default()
17 }
18 .into()
19 }
20
21 pub fn font_fallback_schema(&self) -> Schema {
22 SchemaObject {
23 instance_type: Some(InstanceType::Array.into()),
24 array: Some(Box::new(ArrayValidation {
25 items: Some(schemars::schema::SingleOrVec::Single(Box::new(
26 self.font_family_schema(),
27 ))),
28 unique_items: Some(true),
29 ..Default::default()
30 })),
31 ..Default::default()
32 }
33 .into()
34 }
35}
36
37type PropertyName<'a> = &'a str;
38type ReferencePath<'a> = &'a str;
39
40/// Modifies the provided [`RootSchema`] by adding references to all of the specified properties.
41///
42/// # Examples
43///
44/// ```
45/// # let root_schema = RootSchema::default();
46/// add_references_to_properties(&mut root_schema, &[
47/// ("property_a", "#/definitions/DefinitionA"),
48/// ("property_b", "#/definitions/DefinitionB"),
49/// ])
50/// ```
51pub fn add_references_to_properties(
52 root_schema: &mut RootSchema,
53 properties_with_references: &[(PropertyName, ReferencePath)],
54) {
55 for (property, definition) in properties_with_references {
56 let Some(schema) = root_schema.schema.object().properties.get_mut(*property) else {
57 log::warn!("property '{property}' not found in JSON schema");
58 continue;
59 };
60
61 match schema {
62 Schema::Object(schema) => {
63 schema.reference = Some(definition.to_string());
64 }
65 Schema::Bool(_) => {
66 // Boolean schemas can't have references.
67 }
68 }
69 }
70}