mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-27 03:47:09 -06:00
Keep a document's own styles and defaults when applying a style set (#4013)
Fixes #3650 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
85db9cfef5
commit
b638caa2d2
@@ -169,11 +169,19 @@ fn style_set(s: &mut Session, v: &Value) -> CmdResult {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Keep custom styles and fonts.
|
||||
let customs: Vec<_> = s.doc.styles.styles.iter().filter(|x| !x.builtin).cloned().collect();
|
||||
fresh.styles.extend(customs);
|
||||
fresh.default_chr.font = s.doc.styles.default_chr.font.clone();
|
||||
s.doc.styles = fresh;
|
||||
// Overlay the set onto the document's sheet: every other style, the latent styles and the
|
||||
// document defaults stay as they are (no set defines its own defaults).
|
||||
for mut st in fresh.styles {
|
||||
match s.doc.styles.styles.iter_mut().find(|x| x.id == st.id) {
|
||||
Some(old) => {
|
||||
st.default = old.default;
|
||||
st.locked = old.locked;
|
||||
st.builtin = old.builtin;
|
||||
*old = st;
|
||||
}
|
||||
None => s.doc.styles.styles.push(st),
|
||||
}
|
||||
}
|
||||
let (h, b) = (s.doc.settings.major_font.clone(), s.doc.settings.minor_font.clone());
|
||||
set_fonts(s, &h, &b);
|
||||
set_accent(s, accent);
|
||||
|
||||
@@ -10577,3 +10577,38 @@ fn export_png_refuses_a_path_that_is_not_png() {
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn style_set_keeps_imported_styles_latent_styles_and_defaults() {
|
||||
use wordcraft_doc::props::{Rgb, TextColor};
|
||||
use wordcraft_doc::styles::{Style, StyleKind};
|
||||
for name in ["basic", "lines", "shaded", "casual", "centered", "minimalist", "title"] {
|
||||
let mut s = s();
|
||||
let mut body = s.doc.styles.get("Normal").unwrap().clone();
|
||||
body.id = "BodyText".into();
|
||||
body.name = "Body Text".into();
|
||||
body.builtin = true;
|
||||
body.based_on = Some("Normal".into());
|
||||
body.chr.size = Some(20.0);
|
||||
body.chr.color = Some(TextColor::Rgb(Rgb(0xFF, 0, 0)));
|
||||
let grid = Style { id: "GridTable4".into(), name: "Grid Table 4".into(), kind: StyleKind::Table, builtin: true, ..Default::default() };
|
||||
s.doc.styles.styles.push(body.clone());
|
||||
s.doc.styles.styles.push(grid.clone());
|
||||
s.doc.styles.latent_styles = Some("<w:latentStyles/>".into());
|
||||
s.doc.styles.default_chr.lang = Some("de-DE".into());
|
||||
s.doc.styles.default_chr.size = Some(11.0);
|
||||
run(&mut s, "design.styleSet", json!({ "name": name }));
|
||||
assert_eq!(s.doc.styles.get("BodyText"), Some(&body), "{name}: BodyText");
|
||||
assert_eq!(s.doc.styles.get("GridTable4"), Some(&grid), "{name}: GridTable4");
|
||||
assert_eq!(s.doc.styles.latent_styles.as_deref(), Some("<w:latentStyles/>"), "{name}");
|
||||
assert_eq!(s.doc.styles.default_chr.lang.as_deref(), Some("de-DE"), "{name}");
|
||||
assert_eq!(s.doc.styles.default_chr.size, Some(11.0), "{name}");
|
||||
assert_eq!(s.doc.styles.styles.iter().filter(|x| x.id == "Heading1").count(), 1, "{name}");
|
||||
let saved = crate::io::save_bytes("x.docx", &s.doc).unwrap();
|
||||
let back = crate::io::open_bytes("x.docx", &saved).unwrap();
|
||||
assert!(back.styles.get("BodyText").is_some(), "{name}: BodyText after round trip");
|
||||
}
|
||||
let mut s = s();
|
||||
run(&mut s, "design.styleSet", json!({ "name": "title" }));
|
||||
assert_eq!(s.doc.styles.get("Title").unwrap().chr.size, Some(36.0));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user