Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions Clippit.Tests/Word/RevisionProcessorTests.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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(
"""
<w:p>
<w:hyperlink w:anchor="Target">
<w:r><w:t xml:space="preserve">Alpha </w:t></w:r>
<w:del w:id="1" w:author="Author" w:date="2026-10-15T00:00:00Z">
<w:r><w:delText>beta</w:delText></w:r>
</w:del>
<w:ins w:id="2" w:author="Author" w:date="2026-10-15T00:00:00Z">
<w:r><w:t>delta</w:t></w:r>
</w:ins>
<w:r><w:t xml:space="preserve"> gamma</w:t></w:r>
</w:hyperlink>
</w:p>
<w:p><w:bookmarkStart w:id="0" w:name="Target"/><w:r><w:t>Target</w:t></w:r><w:bookmarkEnd w:id="0"/></w:p>
"""
);

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($"<w:document xmlns:w=\"{W.w.NamespaceName}\"><w:body>{bodyXml}</w:body></w:document>")
);
}
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
5 changes: 4 additions & 1 deletion Clippit/Word/RevisionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading