diff --git a/src/Html2OpenXml/Expressions/Image/ImageExpressionBase.cs b/src/Html2OpenXml/Expressions/Image/ImageExpressionBase.cs
index 3cf0422..0f77f42 100644
--- a/src/Html2OpenXml/Expressions/Image/ImageExpressionBase.cs
+++ b/src/Html2OpenXml/Expressions/Image/ImageExpressionBase.cs
@@ -12,7 +12,6 @@
using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml;
-using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using a = DocumentFormat.OpenXml.Drawing;
@@ -26,6 +25,12 @@ namespace HtmlToOpenXml.Expressions;
///
abstract class ImageExpressionBase(AngleSharp.Dom.IElement node) : HtmlDomExpression
{
+ private readonly RunProperties runProperties = new();
+ private readonly ParagraphProperties paraProperties = new();
+ // some style attributes, such as borders, will convert this node to a framed container
+ private bool renderAsFramed;
+
+
///
public override IEnumerable Interpret (ParsingContext context)
{
@@ -35,16 +40,17 @@ public override IEnumerable Interpret (ParsingContext context)
return [];
Run run = new(drawing);
- Border border = ComposeStyles();
- if (border.Val?.Equals(BorderValues.None) == false)
- {
- run.RunProperties ??= new();
- run.RunProperties.Border = border;
- }
+ ComposeStyles();
+
+ if (runProperties.HasChildren)
+ run.RunProperties = runProperties;
+
+ if (renderAsFramed)
+ return [new Paragraph(paraProperties, run)];
return [run];
}
- private Border ComposeStyles ()
+ private void ComposeStyles ()
{
var styleAttributes = node.GetStyles();
var border = new Border() { Val = BorderValues.None };
@@ -66,7 +72,22 @@ private Border ComposeStyles ()
border.Size = (uint) borderWidth.ValueInPx * 4;
}
}
- return border;
+
+ if (border.Val?.Equals(BorderValues.None) == false)
+ {
+ runProperties.Border = border;
+ }
+
+ // if the layout is not inline and both left and right are auto, image appears centered
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left
+ var margin = styleAttributes.GetMargin("margin");
+ if (margin.Left.Type == UnitMetric.Auto
+ && margin.Right.Type == UnitMetric.Auto
+ && !AngleSharpExtensions.IsInlineLayout(styleAttributes["display"]))
+ {
+ paraProperties.Justification = new() { Val = JustificationValues.Center };
+ renderAsFramed = true;
+ }
}
///
diff --git a/src/Html2OpenXml/Utilities/AngleSharpExtensions.cs b/src/Html2OpenXml/Utilities/AngleSharpExtensions.cs
index 3d89624..bb397a2 100644
--- a/src/Html2OpenXml/Utilities/AngleSharpExtensions.cs
+++ b/src/Html2OpenXml/Utilities/AngleSharpExtensions.cs
@@ -153,4 +153,13 @@ public static string CollapseLineBreaks(this string str)
return new string(chars, 0, length);
}
+
+ ///
+ /// Determines whether the layout mode is inline vs block or flex.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsInlineLayout(string? displayMode)
+ {
+ return displayMode?.StartsWith("inline", StringComparison.OrdinalIgnoreCase) == true;
+ }
}
\ No newline at end of file
diff --git a/src/Html2OpenXml/Utilities/OpenXmlExtensions.cs b/src/Html2OpenXml/Utilities/OpenXmlExtensions.cs
index 5242f49..905ba21 100755
--- a/src/Html2OpenXml/Utilities/OpenXmlExtensions.cs
+++ b/src/Html2OpenXml/Utilities/OpenXmlExtensions.cs
@@ -9,11 +9,9 @@
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*/
-using System;
using System.Runtime.CompilerServices;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;
-using DocumentFormat.OpenXml.Drawing.Wordprocessing;
namespace HtmlToOpenXml;
diff --git a/test/HtmlToOpenXml.Tests/ImgTests.cs b/test/HtmlToOpenXml.Tests/ImgTests.cs
index 15e5596..f335991 100644
--- a/test/HtmlToOpenXml.Tests/ImgTests.cs
+++ b/test/HtmlToOpenXml.Tests/ImgTests.cs
@@ -219,6 +219,21 @@ public async Task ParseIntoDocumentPart_ReturnsImageParentedToPart (Type openXml
AssertThatOpenXmlDocumentIsValid();
}
+ [TestCase("block", ExpectedResult = true)]
+ [TestCase("flex", ExpectedResult = true)]
+ [TestCase("inline", ExpectedResult = false)]
+ public bool CenterImg_ReturnsFramedImg(string displayMode)
+ {
+ var elements = converter.Parse($@"");
+
+ Assert.That(elements, Has.Count.EqualTo(1));
+ Assert.That(elements[0], Is.TypeOf());
+ AssertIsImg(mainPart, elements[0]);
+ return elements[0].GetFirstChild()?.
+ Justification?.Val?.Value == JustificationValues.Center;
+ }
+
private static (Drawing, ImagePart) AssertIsImg (OpenXmlPartContainer container, OpenXmlElement paragraph)
{
var run = paragraph.GetFirstChild();