Skip to content

Commit

Permalink
Ensure to count existing images from header and footer too #113
Browse files Browse the repository at this point in the history
  • Loading branch information
onizet committed Jul 24, 2024
1 parent a97bdfa commit 9b01c5d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
28 changes: 24 additions & 4 deletions src/Html2OpenXml/Expressions/ImageExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using AngleSharp.Html.Dom;
using DocumentFormat.OpenXml;
Expand Down Expand Up @@ -117,12 +118,31 @@ private Border ComposeStyles ()

drawingObjId = 1; // 1 is the minimum ID set by MS Office.
imageObjId = 1;
foreach (var d in context.MainPart.Document.Body!.Descendants<Drawing>())

foreach (var part in new[] {
context.MainPart.Document.Body!.Descendants<Drawing>(),
context.MainPart.HeaderParts.SelectMany(f => f.Header.Descendants<Drawing>()),
context.MainPart.FooterParts.SelectMany(f => f.Footer.Descendants<Drawing>())
})
foreach (Drawing d in part)
{
if (d.Inline == null) continue; // fix some rare issue where Inline is null (reported by scwebgroup)
if (d.Inline!.DocProperties?.Id?.Value > drawingObjId) drawingObjId = d.Inline.DocProperties.Id;
wp.DocProperties? docProperties = null;
pic.NonVisualPictureProperties? nvPr = null;

if (d.Anchor != null)
{
docProperties = d.Anchor.GetFirstChild<wp.DocProperties>();
nvPr = d.Anchor.GetFirstChild<a.Graphic>()?.GraphicData?.GetFirstChild<pic.Picture>()?.GetFirstChild<pic.NonVisualPictureProperties>();
}
else if (d.Inline != null)
{
docProperties = d.Inline!.DocProperties;
nvPr = d.Inline!.Graphic?.GraphicData?.GetFirstChild<pic.NonVisualPictureProperties>();
}

if (docProperties?.Id != null && docProperties.Id.Value > drawingObjId)
drawingObjId = docProperties.Id.Value;

var nvPr = d.Inline!.Graphic?.GraphicData?.GetFirstChild<pic.NonVisualPictureProperties>();
if (nvPr != null && nvPr.NonVisualDrawingProperties?.Id?.Value > imageObjId)
imageObjId = nvPr.NonVisualDrawingProperties.Id;
}
Expand Down
34 changes: 32 additions & 2 deletions test/HtmlToOpenXml.Tests/ImgTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
namespace HtmlToOpenXml.Tests
{
using pic = DocumentFormat.OpenXml.Drawing.Pictures;
using wp = DocumentFormat.OpenXml.Drawing.Wordprocessing;

/// <summary>
/// Tests images.
Expand Down Expand Up @@ -86,9 +87,37 @@ public async Task LoadRemoteImage_BaseUri()
AssertIsImg(elements.First());
}

private void AssertIsImg (OpenXmlCompositeElement elements)
[Test(Description = "Image ID must be unique, amongst header, body and footer parts")]
public async Task UniqueImageIdAcrossPackagingParts()
{
var run = elements.GetFirstChild<Run>();
using var generatedDocument = new MemoryStream();
using (var buffer = ResourceHelper.GetStream("Resources.DocWithImgHeaderFooter.docx"))
buffer.CopyTo(generatedDocument);

generatedDocument.Position = 0L;
using WordprocessingDocument package = WordprocessingDocument.Open(generatedDocument, true);
MainDocumentPart mainPart = package.MainDocumentPart;

var beforeMaxDocPropId = new[] {
mainPart.Document.Body!.Descendants<wp.DocProperties>(),
mainPart.HeaderParts.SelectMany(x => x.Header.Descendants<wp.DocProperties>()),
mainPart.FooterParts.SelectMany(x => x.Footer.Descendants<wp.DocProperties>())
}.SelectMany(x => x).MaxBy(x => x.Id?.Value ?? 0).Id.Value;

HtmlConverter converter = new(mainPart);
await converter.ParseHtml("<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' width='42' height='42'>");
mainPart.Document.Save();

var img = mainPart.Document.Body!.Descendants<Drawing>().FirstOrDefault();
Assert.That(img, Is.Not.Null);
Assert.That(img.Inline.DocProperties.Id.Value,
Is.GreaterThan(beforeMaxDocPropId),
"New image id is incremented considering existing images in header, body and footer");
}

private Drawing AssertIsImg (OpenXmlCompositeElement element)
{
var run = element.GetFirstChild<Run>();
Assert.That(run, Is.Not.Null);
var img = run.GetFirstChild<Drawing>();
Assert.That(img, Is.Not.Null);
Expand All @@ -99,6 +128,7 @@ private void AssertIsImg (OpenXmlCompositeElement elements)
var imagePartId = pic.BlipFill.Blip.Embed.Value;
var part = mainPart.GetPartById(imagePartId);
Assert.That(part, Is.TypeOf(typeof(ImagePart)));
return img;
}
}
}
Binary file not shown.

0 comments on commit 9b01c5d

Please sign in to comment.