mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-27 20:07:19 -06:00
#3692: a glossary is written from the model when the privacy settings ask for changes
Finding 72. An unchanged glossary was carried byte for byte, judged by a fingerprint of its entries that leaves out the document's privacy settings, so a save with "remove personal information" or "remove date and time" kept the authors and dates of the glossary's tracked changes. With either setting on, the glossary is now written from the model, which applies them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
23b9721720
commit
01c78899ce
@@ -268,7 +268,10 @@ pub(crate) fn write_parts(doc: &Document, flavor: Flavor) -> Result<Vec<(String,
|
||||
|
||||
// The glossary: kept verbatim while its entries are as read and its parts were kept, else
|
||||
// written from the model (before the notes: references its entries hold are collected too).
|
||||
if glossary::edited(doc) || (!doc.glossary.is_empty() && !wr.embeds.kept_glossary()) {
|
||||
// Also written from the model when the privacy settings ask for changes: kept bytes would
|
||||
// carry the names and dates of its tracked changes (#3692).
|
||||
let private = doc.settings.remove_personal_info || doc.settings.remove_date_time;
|
||||
if private || glossary::edited(doc) || (!doc.glossary.is_empty() && !wr.embeds.kept_glossary()) {
|
||||
wr.embeds.drop_glossary = true;
|
||||
wr.glossary(&mut entries, &mut overrides, &mut rels);
|
||||
}
|
||||
|
||||
@@ -234,6 +234,34 @@ fn edited_glossary_is_written_from_the_model() {
|
||||
assert_eq!(twice.get(&target), files.get(&target));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_unchanged_glossary_follows_the_privacy_settings() {
|
||||
// An untouched glossary was written back byte for byte, so the names and dates of its
|
||||
// tracked changes survived a save that removes personal information (#3692).
|
||||
let tracked = r#"<w:docPart><w:docPartPr><w:name w:val="Clause"/><w:category><w:name w:val="General"/><w:gallery w:val="docParts"/></w:category></w:docPartPr><w:docPartBody><w:p><w:ins w:id="1" w:author="Quill Ramsey" w:date="2026-03-04T05:06:07Z"><w:r><w:t>Added clause</w:t></w:r></w:ins></w:p></w:docPartBody></w:docPart>"#;
|
||||
let bytes = package(
|
||||
&[("rId7", GLOSSARY_REL, "glossary/document.xml")],
|
||||
&[
|
||||
("[Content_Types].xml", content_types(&[("/word/glossary/document.xml", GLOSSARY_CT)])),
|
||||
("word/glossary/document.xml", glossary_xml(tracked)),
|
||||
],
|
||||
);
|
||||
let doc = wordcraft_docx::read(&bytes).unwrap();
|
||||
let as_read = save(&doc);
|
||||
let kept = text(&as_read, &glossary_target(&as_read).expect("a glossary"));
|
||||
assert!(kept.contains("Quill Ramsey"), "the fixture's glossary is kept verbatim: {kept}");
|
||||
for (personal, dates) in [(true, false), (false, true), (true, true)] {
|
||||
let mut private = doc.clone();
|
||||
private.settings.remove_personal_info = personal;
|
||||
private.settings.remove_date_time = dates;
|
||||
let files = save(&private);
|
||||
let g = text(&files, &glossary_target(&files).expect("a glossary"));
|
||||
assert!(g.contains("Added clause"), "{g}");
|
||||
assert_eq!(g.contains("Quill Ramsey"), !personal, "{g}");
|
||||
assert_eq!(g.contains("2026-03-04T05:06:07Z"), !dates, "{g}");
|
||||
}
|
||||
}
|
||||
|
||||
/// The relationships part of a part in `word/`.
|
||||
fn glossary_rels(part: &str) -> String {
|
||||
let (dir, file) = part.rsplit_once('/').unwrap();
|
||||
|
||||
Reference in New Issue
Block a user