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