diff --git a/crates/engine/src/cmd/textstyles.rs b/crates/engine/src/cmd/textstyles.rs index 4987c479f..a44dd1773 100644 --- a/crates/engine/src/cmd/textstyles.rs +++ b/crates/engine/src/cmd/textstyles.rs @@ -475,8 +475,9 @@ fn name_param<'a>(p: &'a Value, kind: Kind, verb: &str) -> Result<&'a str> { str_param(p, "name").ok_or_else(|| bad(&kind.cmd(verb), "missing `name`")) } -/// The `attrs` of `p`, validated. `kept` holds the style's current attributes (`charStyle.edit`): -/// a language tag that is not in the list, which a file can give a style, stays when `attrs` keeps it. +/// The `attrs` of `p`, validated. `kept` holds the style's current attributes (`charStyle.edit`) or +/// the target text's attributes (`charStyle.new`): a language tag that is not in the list, which a +/// file can give a style or a run, stays when `attrs` keeps it. fn attrs_param(p: &Value, kind: Kind, verb: &str, kept: Option<&Map>) -> Result>> { match p.get("attrs") { None | Some(Value::Null) => Ok(None), @@ -536,9 +537,10 @@ fn list(s: &mut Session, kind: Kind) -> Result { fn new(s: &mut Session, p: &Value, kind: Kind) -> Result { let c = kind.cmd("new"); - let attrs = match attrs_param(p, kind, "new", None)? { + let target = selection_attrs(s, p, kind)?; + let attrs = match attrs_param(p, kind, "new", target.as_ref())? { Some(a) => a, - None => match selection_attrs(s, p, kind)? { + None => match target { Some(a) => a, None => { let a = new_style_attrs(s, kind); diff --git a/crates/engine/src/cmd/textstyles/tests.rs b/crates/engine/src/cmd/textstyles/tests.rs index bb37dd877..d7021efda 100644 --- a/crates/engine/src/cmd/textstyles/tests.rs +++ b/crates/engine/src/cmd/textstyles/tests.rs @@ -245,6 +245,18 @@ fn character_style_options_edit_keeps_a_language_tag_from_a_file() { assert!(error.contains("unknown language"), "{error}"); } +#[test] +fn new_character_style_keeps_a_language_tag_from_the_text() { + let (mut s, id) = session_with_text("Text"); + if let Some(NodeKind::Text(t)) = std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc).node_mut(NodeId(id)).map(|n| &mut n.kind) { + t.runs[0].style.language = Some("x-file".into()); + } + s.execute("charStyle.new", &json!({"name":"Body","id":id,"attrs":{"size":18.0,"language":"x-file"}})).unwrap(); + assert_eq!(s.doc().unwrap().doc.char_styles.iter().find(|d| d.name == "Body").unwrap().attrs["language"], json!("x-file")); + let error = s.execute("charStyle.new", &json!({"name":"Other","id":id,"attrs":{"language":"x-other"}})).unwrap_err().to_string(); + assert!(error.contains("unknown language"), "{error}"); +} + #[test] fn editing_character_style_clears_removed_size_without_losing_local_override() { let (mut s, id) = session_with_text("One two");