diff --git a/src/Html2OpenXml/Expressions/ImageExpression.cs b/src/Html2OpenXml/Expressions/ImageExpression.cs
index e23ed61..286de70 100644
--- a/src/Html2OpenXml/Expressions/ImageExpression.cs
+++ b/src/Html2OpenXml/Expressions/ImageExpression.cs
@@ -11,6 +11,7 @@
*/
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using AngleSharp.Html.Dom;
using DocumentFormat.OpenXml;
@@ -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())
+
+ foreach (var part in new[] {
+ context.MainPart.Document.Body!.Descendants(),
+ context.MainPart.HeaderParts.SelectMany(f => f.Header.Descendants()),
+ context.MainPart.FooterParts.SelectMany(f => f.Footer.Descendants())
+ })
+ 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();
+ nvPr = d.Anchor.GetFirstChild()?.GraphicData?.GetFirstChild()?.GetFirstChild();
+ }
+ else if (d.Inline != null)
+ {
+ docProperties = d.Inline!.DocProperties;
+ nvPr = d.Inline!.Graphic?.GraphicData?.GetFirstChild();
+ }
+
+ if (docProperties?.Id != null && docProperties.Id.Value > drawingObjId)
+ drawingObjId = docProperties.Id.Value;
- var nvPr = d.Inline!.Graphic?.GraphicData?.GetFirstChild();
if (nvPr != null && nvPr.NonVisualDrawingProperties?.Id?.Value > imageObjId)
imageObjId = nvPr.NonVisualDrawingProperties.Id;
}
diff --git a/test/HtmlToOpenXml.Tests/ImgTests.cs b/test/HtmlToOpenXml.Tests/ImgTests.cs
index d79cd01..f1fe8a6 100644
--- a/test/HtmlToOpenXml.Tests/ImgTests.cs
+++ b/test/HtmlToOpenXml.Tests/ImgTests.cs
@@ -6,6 +6,7 @@
namespace HtmlToOpenXml.Tests
{
using pic = DocumentFormat.OpenXml.Drawing.Pictures;
+ using wp = DocumentFormat.OpenXml.Drawing.Wordprocessing;
///
/// Tests images.
@@ -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();
+ 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(),
+ mainPart.HeaderParts.SelectMany(x => x.Header.Descendants()),
+ mainPart.FooterParts.SelectMany(x => x.Footer.Descendants())
+ }.SelectMany(x => x).MaxBy(x => x.Id?.Value ?? 0).Id.Value;
+
+ HtmlConverter converter = new(mainPart);
+ await converter.ParseHtml("");
+ mainPart.Document.Save();
+
+ var img = mainPart.Document.Body!.Descendants().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();
Assert.That(run, Is.Not.Null);
var img = run.GetFirstChild();
Assert.That(img, Is.Not.Null);
@@ -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;
}
}
}
\ No newline at end of file
diff --git a/test/HtmlToOpenXml.Tests/Resources/DocWithImgHeaderFooter.docx b/test/HtmlToOpenXml.Tests/Resources/DocWithImgHeaderFooter.docx
new file mode 100644
index 0000000..99790b2
Binary files /dev/null and b/test/HtmlToOpenXml.Tests/Resources/DocWithImgHeaderFooter.docx differ