diff --git a/Clippit.Tests/Word/RevisionProcessorTests.cs b/Clippit.Tests/Word/RevisionProcessorTests.cs index 6ab568e7..5caad22e 100644 --- a/Clippit.Tests/Word/RevisionProcessorTests.cs +++ b/Clippit.Tests/Word/RevisionProcessorTests.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Xml.Linq; using Clippit.Word; +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Packaging; namespace Clippit.Tests.Word; @@ -102,5 +105,53 @@ public void RP001(string name) if (rejectedRevisions.Any()) Assert.Fail($"Regression: Rejected output differs from baseline for {name}"); } + + [Test] + [Arguments(false, "Alpha delta gamma")] + [Arguments(true, "Alpha beta gamma")] + public async Task RP053_RevisionsInsideHyperlink(bool reject, string expectedText) + { + var source = CreateDocument( + """ + + + Alpha + + beta + + + delta + + gamma + + + Target + """ + ); + + var processed = reject ? RevisionProcessor.RejectRevisions(source) : RevisionProcessor.AcceptRevisions(source); + + using var streamDoc = new OpenXmlMemoryStreamDocument(processed); + using var doc = streamDoc.GetWordprocessingDocument(); + await Validate(doc); + await Assert.That(RevisionProcessor.HasTrackedRevisions(doc)).IsFalse(); + var hyperlink = doc.MainDocumentPart!.GetXDocument().Descendants(W.hyperlink).Single(); + await Assert.That(TextOf(hyperlink)).IsEqualTo(expectedText); + } + + private static WmlDocument CreateDocument(string bodyXml) + { + using var stream = new MemoryStream(); + using (var doc = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document)) + { + var mainPart = doc.AddMainDocumentPart(); + mainPart.PutXDocument( + XDocument.Parse($"{bodyXml}") + ); + } + return new WmlDocument("RevisionProcessorTest.docx", stream.ToArray()); + } + + private static string TextOf(XElement element) => string.Concat(element.Descendants(W.t).Select(t => t.Value)); } #pragma warning restore CA1707 diff --git a/Clippit/Word/RevisionProcessor.cs b/Clippit/Word/RevisionProcessor.cs index cdfa1c3f..3a83d437 100644 --- a/Clippit/Word/RevisionProcessor.cs +++ b/Clippit/Word/RevisionProcessor.cs @@ -380,9 +380,12 @@ private static object ReverseRevisionsTransform(XNode node, ReverseRevisionsInfo { if (node is not XElement element) return node; + // Run-level revisions may be wrapped in these containers; they belong to the enclosing paragraph. var parent = element .Ancestors() - .FirstOrDefault(a => a.Name != W.sdtContent && a.Name != W.sdt && a.Name != W.smartTag); + .FirstOrDefault(a => + a.Name != W.sdtContent && a.Name != W.sdt && a.Name != W.smartTag && a.Name != W.hyperlink + ); //////////////////////////////////////////////////////////////////////////////////// // Deleted run