- 1001
} - 1002
} - 1003
} - 1004
work.put(&doc.part, splice.apply(&doc.bytes, &doc.part)?); - 1005
Ok(Outcome { - 1006
summary: format!("{anchor} deleted as a tracked change"), - 1007
expect: vec![Expect::UnitDeleted { - 1008
anchor: anchor.to_string(), - 1009
}], - 1010
created: Vec::new(), - 1011
}) - 1012
} - 1013
- 1014
/// The prefix bound to the Word 2010 namespace, and the rewritten root - 1015
/// start tag when it had to be declared (plus `mc:Ignorable`). - 1016
#[allow(clippy::type_complexity)] - 1017
fn ensure_w14(doc: &Doc) -> Result<(String, Option<(std::ops::Range<usize>, String)>), EditError> { - 1018
if let Some(prefix) = doc.tree.prefix_for(W14) { - 1019
return Ok((prefix, None)); - 1020
} - 1021
let root = doc.tree.root(); - 1022
let mut attributes = root.element.attributes.clone(); - 1023
if attributes.iter().any(|(key, _)| key == "xmlns:w14") { - 1024
return fail("the document binds the w14 prefix to another namespace"); - 1025
} - 1026
attributes.push(("xmlns:w14".into(), W14.into())); - 1027
let mc = match doc.tree.prefix_for(MC) { - 1028
Some(prefix) => prefix, - 1029
None => { - 1030
if attributes.iter().any(|(key, _)| key == "xmlns:mc") { - 1031
return fail("the document binds the mc prefix to another namespace"); - 1032
} - 1033
attributes.push(("xmlns:mc".into(), MC.into())); - 1034
"mc:".into() - 1035
} - 1036
}; - 1037
let ignorable = format!("{mc}Ignorable"); - 1038
match attributes.iter_mut().find(|(key, _)| *key == ignorable) { - 1039
Some((_, value)) => { - 1040
if !value.split_whitespace().any(|prefix| prefix == "w14") { - 1041
value.push_str(" w14"); - 1042
} - 1043
} - 1044
None => attributes.push((ignorable, "w14".into())), - 1045
} - 1046
let tag = start_tag(&root.element.name, &attributes, root.is_empty_element()); - 1047
let end = if root.is_empty_element() { - 1048
root.span.end - 1049
} else { - 1050
root.inner.start - 1051
}; - 1052
Ok(("w14:".into(), Some((root.span.start..end, tag)))) - 1053
} - 1054
- 1055
/// `count` paragraph ids no paragraph of the document uses, lowest first, - 1056
/// so replaying the same ops on the same document mints the same ids. - 1057
fn new_para_ids(doc: &Doc, count: usize) -> Vec<String> { - 1058
let existing: std::collections::HashSet<String> = doc - 1059
.tree - 1060
.nodes - 1061
.iter() - 1062
.filter_map(|node| node.element.attr("paraId")) - 1063
.map(str::to_ascii_uppercase) - 1064
.collect(); - 1065
let mut ids: Vec<String> = (0x1A00_0001u32..0x7FFF_FFFF) - 1066
.map(|value| format!("{value:08X}")) - 1067
.filter(|candidate| !existing.contains(candidate)) - 1068
.take(count) - 1069
.collect(); - 1070
while ids.len() < count { - 1071
ids.push("7FFFFFFE".into()); - 1072
} - 1073
ids - 1074
} - 1075
- 1076
/// A paragraph style by id or by display name (`Heading 1`). - 1077
fn resolve_style<R: Read + Seek>( - 1078
work: &mut Work<'_, R>, - 1079
wanted: &str, - 1080
) -> Result<String, EditError> { - 1081
let main = work.main_part(); - 1082
let Some(part) = work.related(&main, "styles")? else { - 1083
return fail("the document has no styles part, so no style can be applied"); - 1084
}; - 1085
let bytes = work.get(&part)?; - 1086
let tree = Tree::parse(&bytes, &part, work.limits())?; - 1087
let mut available = Vec::new(); - 1088
for style in tree.descendants(0, "style") { - 1089
let element = &tree.nodes[style].element; - 1090
if element.attr("type") != Some("paragraph") { - 1091
continue; - 1092
} - 1093
let Some(id) = element.attr("styleId") else { - 1094
continue; - 1095
}; - 1096
let name = tree - 1097
.children(style, "name") - 1098
.next() - 1099
.and_then(|name| tree.nodes[name].element.attr("val")) - 1100
.unwrap_or(id); - 1101
if id == wanted || name.eq_ignore_ascii_case(wanted) || id.eq_ignore_ascii_case(wanted) { - 1102
return Ok(id.to_string()); - 1103
} - 1104
available.push(name.to_string()); - 1105
} - 1106
available.truncate(30); - 1107
fail(format!( - 1108
"no paragraph style {wanted:?}; available: {}", - 1109
available.join(", ") - 1110
)) - 1111
} - 1112
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.