mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-09 20:00:11 -06:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5808531e53 | ||
|
|
472ee9b04a |
+2
-1
File diff suppressed because one or more lines are too long
@@ -364,6 +364,11 @@ pub fn read_with_password(bytes: &[u8], password: Option<&str>) -> Result<Docume
|
|||||||
// Sections: each section's properties attach to the paragraph that ends it (its story of
|
// Sections: each section's properties attach to the paragraph that ends it (its story of
|
||||||
// header/footer parts included); the section reaching the end of the text is the final one.
|
// header/footer parts included); the section reaching the end of the text is the final one.
|
||||||
let mut paras = walk(&ctx, 0, fib.ccp.text, &mut pics);
|
let mut paras = walk(&ctx, 0, fib.ccp.text, &mut pics);
|
||||||
|
// The first paragraph ending at each CP, found once rather than by a scan per section.
|
||||||
|
let mut ending: std::collections::HashMap<u32, usize> = std::collections::HashMap::new();
|
||||||
|
for (i, p) in paras.iter().enumerate() {
|
||||||
|
ending.entry(p.end_cp).or_insert(i);
|
||||||
|
}
|
||||||
let last = sects.last().map(|s| s.props.clone());
|
let last = sects.last().map(|s| s.props.clone());
|
||||||
for (si, sec) in sects.iter().enumerate() {
|
for (si, sec) in sects.iter().enumerate() {
|
||||||
let mut props = sec.props.clone();
|
let mut props = sec.props.clone();
|
||||||
@@ -374,11 +379,8 @@ pub fn read_with_password(bytes: &[u8], password: Option<&str>) -> Result<Docume
|
|||||||
if is_final {
|
if is_final {
|
||||||
continue; // handled below through `last`
|
continue; // handled below through `last`
|
||||||
}
|
}
|
||||||
for p in paras.iter_mut() {
|
if let Some(p) = ending.get(&sec.end_cp).and_then(|&i| paras.get_mut(i)) {
|
||||||
if p.end_cp == sec.end_cp {
|
p.para.section = Some(Box::new(props));
|
||||||
p.para.section = Some(Box::new(props));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(mut l) = last {
|
if let Some(mut l) = last {
|
||||||
|
|||||||
@@ -1018,6 +1018,32 @@ fn two_sections_box_the_first() {
|
|||||||
assert!(!doc.last_section.title_page);
|
assert!(!doc.last_section.title_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sections_ending_off_a_paragraph_mark_attach_nowhere() {
|
||||||
|
// Hostile section ends that miss every paragraph mark are skipped; the one that ends a
|
||||||
|
// paragraph still boxes it. Paragraphs are found by their end, not scanned per section.
|
||||||
|
let mut sections: Vec<(u32, Vec<u8>)> = (1..6).map(|cp| (cp, Vec::new())).collect();
|
||||||
|
sections.push((6, grpprl(&[(0x300A, &[0x01])])));
|
||||||
|
sections.push((12, Vec::new()));
|
||||||
|
let spec = StructSpec {
|
||||||
|
text: "first\rsecond\r",
|
||||||
|
header_stories: vec![],
|
||||||
|
sections,
|
||||||
|
chpx_runs: vec![(0, Vec::new())],
|
||||||
|
papx_entries: vec![(0, 0, Vec::new()), (6, 0, Vec::new())],
|
||||||
|
plf_lst: Vec::new(),
|
||||||
|
plf_lfo: Vec::new(),
|
||||||
|
note_stories: vec![],
|
||||||
|
endnote_stories: vec![],
|
||||||
|
extra_pairs: Vec::new(),
|
||||||
|
data_stream: Vec::new(),
|
||||||
|
};
|
||||||
|
let doc = read(&struct_doc(&spec)).expect("opens");
|
||||||
|
let paras: Vec<_> = doc.body.iter().filter_map(|b| b.as_para()).collect();
|
||||||
|
assert!(paras.first().and_then(|p| p.section.as_ref()).expect("first paragraph boxed").title_page);
|
||||||
|
assert_eq!(paras.iter().filter(|p| p.section.is_some()).count(), 1, "the missing ends attach nowhere");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn header_story_becomes_part() {
|
fn header_story_becomes_part() {
|
||||||
let spec = StructSpec {
|
let spec = StructSpec {
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user