git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commit1d9596e25faa433becee6d6d9bbc8bb521471a41
parenteb6c71cd7a
authorLucas Galante <[email protected]>
date2026-07-01 19:56
Fix KDL type annotation quoting for special chars and add desktop_grid_scale mapping

 src/config.rs | 39 +++++++++++++++++++++++++++++++++++++--
 src/layout.rs |  1 +
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/src/config.rs b/src/config.rs
index 382f7a8..dcfd83c 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -538,6 +538,41 @@ mod tests {
         assert_eq!(ty2, Some("bool".to_string()));
     }
 
+    #[test]
+    fn test_json_to_kdl_with_special_annotations() {
+        let mut annotations = std::collections::HashMap::new();
+        annotations.insert("style.surface.desktop.mode".to_string(), "menu:grid,solid".to_string());
+        
+        let mut desktop_map = serde_json::Map::new();
+        desktop_map.insert("mode".to_string(), serde_json::Value::String("grid".to_string()));
+        
+        let mut surface_map = serde_json::Map::new();
+        surface_map.insert("desktop".to_string(), serde_json::Value::Object(desktop_map));
+        
+        let mut style_map = serde_json::Map::new();
+        style_map.insert("surface".to_string(), serde_json::Value::Object(surface_map));
+        
+        let mut root_map = serde_json::Map::new();
+        root_map.insert("style".to_string(), serde_json::Value::Object(style_map));
+        
+        let root = serde_json::Value::Object(root_map);
+        let kdl_str = json_to_kdl_string_with_annotations(&root, &annotations);
+        println!("Generated KDL:\n{}", kdl_str);
+        
+        let doc_parsed = kdl_str.parse::<kdl::KdlDocument>();
+        assert!(doc_parsed.is_ok(), "Failed to parse KDL: {:?}", doc_parsed.err());
+    }
+}
+
+fn format_kdl_type(ty: &str) -> String {
+    let is_ident = !ty.is_empty()
+        && !ty.chars().next().unwrap().is_ascii_digit()
+        && ty.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '-' | '+' | '?' | '!' | '@' | '*' | '~' | '|' | '.'));
+    if is_ident {
+        ty.to_string()
+    } else {
+        format!("\"{}\"", ty.replace('\\', "\\\\").replace('"', "\\\""))
+    }
 }
 
 pub fn value_to_kdl(key: &str, val: &serde_json::Value, indent: usize) -> String {
@@ -597,7 +632,7 @@ pub fn value_to_kdl_with_annotations(
                         _ => (prop_val.to_string(), None),
                     };
                     if let Some(ty) = val_ty {
-                        prop_parts.push(format!("{}=({}){}", prop_name, ty, val_str));
+                        prop_parts.push(format!("{}=({}){}", prop_name, format_kdl_type(&ty), val_str));
                     } else {
                         prop_parts.push(format!("{}={}", prop_name, val_str));
                     }
@@ -638,7 +673,7 @@ pub fn value_to_kdl_with_annotations(
                 _ => (val.to_string(), None),
             };
             if let Some(ty) = val_ty {
-                format!("{}{} ({}){}\n", indent_str, key, ty, val_str)
+                format!("{}{} ({}){}\n", indent_str, key, format_kdl_type(&ty), val_str)
             } else {
                 format!("{}{} {}\n", indent_str, key, val_str)
             }
diff --git a/src/layout.rs b/src/layout.rs
index 0b127b2..1ca82a2 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -135,6 +135,7 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
                 "style.surface.desktop.cell_fade_inset" => "desktop_cell_fade_inset",
                 "style.surface.desktop.mode" => "desktop_mode",
                 "style.surface.desktop.solid_color" => "desktop_solid_color",
+                "style.surface.desktop.grid_cell_size" => "desktop_grid_scale",
                 "style.surface.plate.padding" => "plate_padding",
                 "style.surface.backplate.color" => "backplate_color",
                 "style.surface.backplate.blur" => "backplate_blur",