mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 12:13:19 +00:00
Merge pull request #5893 from dotCooCoo/fix/empty-thread-frame-style
Text: empty later frames preserve an edited paragraph style
This commit is contained in:
@@ -20,6 +20,25 @@ fn text(s: &Session, id: u64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_later_frames_keep_the_first_frames_edited_paragraph_style() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width": 600, "height": 300})).unwrap();
|
||||
let a =
|
||||
s.execute("text.create", &json!({"x": 10, "y": 10, "text": "First", "area": {"width": 150, "height": 60}})).unwrap()["id"].as_u64().unwrap();
|
||||
let b = s.execute("shape.rectangle", &json!({"x": 200, "y": 10, "width": 150, "height": 60})).unwrap()["id"].as_u64().unwrap();
|
||||
let c = s.execute("shape.rectangle", &json!({"x": 400, "y": 10, "width": 150, "height": 60})).unwrap()["id"].as_u64().unwrap();
|
||||
s.execute("select.set", &json!({"ids": [a, b, c]})).unwrap();
|
||||
s.execute("text.thread.create", &json!({})).unwrap();
|
||||
assert_eq!([text(&s, a), text(&s, b), text(&s, c)], ["First", "", ""]);
|
||||
s.execute("text.setFormat", &json!({"ids": [a], "hyphenate": true})).unwrap();
|
||||
let hyphenates = |id| match &s.doc().unwrap().doc.node(NodeId(id)).unwrap().kind {
|
||||
NodeKind::Text(t) => t.para_at(0).hyphenate,
|
||||
_ => panic!("not text"),
|
||||
};
|
||||
assert_eq!([hyphenates(a), hyphenates(b), hyphenates(c)], [true, true, true]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thread_flows_reflows_on_edit_and_survives_delete() {
|
||||
let (mut s, a, b) = setup();
|
||||
|
||||
@@ -34,7 +34,11 @@ pub fn story_paras(frames: &[&TextObject], later_wins: &[bool]) -> Vec<ParaStyle
|
||||
}
|
||||
out.extend(styles);
|
||||
let text = f.plain_text();
|
||||
prev_empty_tail = text.is_empty() || text.ends_with('\n') || out.is_empty();
|
||||
// An empty frame has no paragraph boundary of its own. Keep the preceding frame's
|
||||
// boundary state so another empty frame cannot replace a paragraph's edited style.
|
||||
if !text.is_empty() {
|
||||
prev_empty_tail = text.ends_with('\n') || out.is_empty();
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
@@ -144,6 +144,25 @@ fn paragraph_styles_flow_with_their_paragraphs() {
|
||||
assert_eq!(story_paras(&[&fa, &fb], &[false, false])[0].justify, Left);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_frames_do_not_replace_an_earlier_paragraph_style() {
|
||||
let mut first = frame(0.0);
|
||||
first.runs = vec![TextRun { text: "First".into(), style: CharStyle::default(), inline: None }];
|
||||
first.set_all_paras(ParaStyle { justify: Justify::Right, ..Default::default() });
|
||||
let middle = frame(200.0);
|
||||
let last = frame(400.0);
|
||||
assert_eq!(story_paras(&[&first, &middle, &last], &[true, false, false])[0].justify, Justify::Right);
|
||||
|
||||
// An empty frame between two parts of the same paragraph changes no style either.
|
||||
let mut last_with_text = last.clone();
|
||||
last_with_text.runs = vec![TextRun { text: "Tail".into(), style: CharStyle::default(), inline: None }];
|
||||
assert_eq!(story_paras(&[&first, &middle, &last_with_text], &[true, false, false])[0].justify, Justify::Right);
|
||||
|
||||
let mut restyled_middle = middle.clone();
|
||||
restyled_middle.set_all_paras(ParaStyle { justify: Justify::Center, ..Default::default() });
|
||||
assert_eq!(story_paras(&[&first, &restyled_middle, &last], &[false, true, false])[0].justify, Justify::Center);
|
||||
}
|
||||
|
||||
/// Numbered list paragraphs count on from one frame to the next: the second frame's first
|
||||
/// whole paragraph takes the next number. A paragraph split between the frames has its number
|
||||
/// in the first frame only, and the paragraph after it takes the next number.
|
||||
|
||||
Reference in New Issue
Block a user