diff --git a/crates/engine/src/cmd/shape/freeform.rs b/crates/engine/src/cmd/shape/freeform.rs index c0430c85f..5fd299c9e 100644 --- a/crates/engine/src/cmd/shape/freeform.rs +++ b/crates/engine/src/cmd/shape/freeform.rs @@ -43,7 +43,7 @@ pub(super) fn connect(s: &mut Session, p: &Value) -> Result { let id = match id_param(p, "id", "shape.connect")? { // The ends are in slide space and rerouting follows the slide's own connectors, so a line // inside a group would be drawn in the group's space and never follow its shapes. - Some(id) if !st.shapes().iter().any(|sh| sh.id == id) && st.shape(id).is_some() => { + Some(id) if !st.shapes().iter().any(|sh| sh.id == id) && st.shape(id).is_some_and(|sh| sh.is_line()) => { return Err(bad("shape.connect", "`id` names a line inside a group; ungroup it first, or leave `id` out for a new connector")); } Some(id) => id, diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index db23c803a..7f59ced53 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -6569,6 +6569,10 @@ fn shape_connect_glues_to_a_shape_inside_a_group() { let e = s.execute("shape.connect", &json!({"id": m, "from": c, "to": b})).unwrap_err().to_string(); assert!(e.contains("inside a group"), "{e}"); assert_eq!(s.doc().unwrap().doc, before, "nothing changed"); + // A grouped shape that is not a line is refused as not a line, not as a grouped line. + let e = s.execute("shape.connect", &json!({"id": n, "from": c, "to": b})).unwrap_err().to_string(); + assert!(e.contains("not a line"), "{e}"); + assert_eq!(s.doc().unwrap().doc, before, "nothing changed"); } /// The outline exports (PowerPoint's outline view) holds titles and body text only: footer,