Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 3.2.1 #170

Merged
merged 14 commits into from
Oct 16, 2024
Merged
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 3.2.1

- Fix indentation of numbering list #166
- Bordered container must render its content with one bordered frame #168
- Fix serialisation of the "Harvard" style for lower-roman list
- Fix ParseHeader/Footer where input with multiple paragraphs output only the latest
- Ensure to apply default style for paragraphs, to avoid a paragraph between 2 list is mis-guessed

## 3.2.0

- Add new public API to allow parsing into Header and Footer #162. Some API methods as been flagged as obsolete with a clear message of what to use instead.
Expand Down
2 changes: 1 addition & 1 deletion HtmlToOpenXml.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 17
# Visual Studio Version 17
VisualStudioVersion = 17.8.34511.84
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlToOpenXml", "src\Html2OpenXml\HtmlToOpenXml.csproj", "{EF700F30-C9BB-49A6-912C-E3B77857B514}"
Expand Down
13 changes: 6 additions & 7 deletions examples/Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ static class Program
static async Task Main(string[] args)
{
const string filename = "test.docx";
string html = ResourceHelper.GetString("Resources.AdvancedTable.html");
string html = ResourceHelper.GetString("Resources.CompleteRunTest.html");
if (File.Exists(filename)) File.Delete(filename);

using (MemoryStream generatedDocument = new MemoryStream())
Expand All @@ -28,8 +28,8 @@ static async Task Main(string[] args)
}

generatedDocument.Position = 0L;
using (WordprocessingDocument package = WordprocessingDocument.Open(generatedDocument, true))
//using (WordprocessingDocument package = WordprocessingDocument.Create(generatedDocument, WordprocessingDocumentType.Document))
//using (WordprocessingDocument package = WordprocessingDocument.Open(generatedDocument, true))
using (WordprocessingDocument package = WordprocessingDocument.Create(generatedDocument, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = package.MainDocumentPart;
if (mainPart == null)
Expand All @@ -38,12 +38,11 @@ static async Task Main(string[] args)
new Document(new Body()).Save(mainPart);
}

HtmlConverter converter = new HtmlConverter(mainPart);
HtmlConverter converter = new(mainPart, new HtmlToOpenXml.IO.DefaultWebRequest(){
BaseImageUrl = new Uri(Path.Combine(Environment.CurrentDirectory, "images"))
});
converter.RenderPreAsTable = true;
Body body = mainPart.Document.Body;

await converter.ParseBody(html);
mainPart.Document.Save();

AssertThatOpenXmlDocumentIsValid(package);
}
Expand Down
14 changes: 13 additions & 1 deletion examples/Demo/Resources/CompleteRunTest.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,19 @@ <h5>Heading 5</h5>
line below! </pre>

</div>


<div style='margin-top: 20px; border: 1px dashed rgba(0, 0, 0, 0.4); background: olive; color: white; display: flex; gap: 5px; padding: 6px 8px; font-size: 14px;'>
<div>
<p>Header placeholder:</p>
<ol>
<li>Item 1</li>
<li>Item 2</li>
</ol>
<p style='text-indent: 4.5em'>Footer Placeholder</p>
</div>
</div>

<div style="border: 1px dashed salmon; margin: 1em">Lorem Ipsum</div>
<!--<div style="page-break-before: always">
New page
</div>-->
Expand Down
97 changes: 0 additions & 97 deletions examples/Demo/Resources/Demo.html

This file was deleted.

57 changes: 0 additions & 57 deletions examples/Demo/Resources/Demo2.html

This file was deleted.

106 changes: 90 additions & 16 deletions src/Html2OpenXml/Expressions/BlockElementExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,68 @@ namespace HtmlToOpenXml.Expressions;
/// Process the parsing of block contents (like <c>p</c>, <c>span</c>, <c>heading</c>).
/// A block-level element always starts on a new line, and the browsers automatically add some space (a margin) before and after the element.
/// </summary>
class BlockElementExpression(IHtmlElement node, params OpenXmlLeafElement[]? styleProperty) : PhrasingElementExpression(node)
class BlockElementExpression: PhrasingElementExpression
{
private readonly OpenXmlLeafElement[]? defaultStyleProperties = styleProperty;
private readonly OpenXmlLeafElement[]? defaultStyleProperties;
protected readonly ParagraphProperties paraProperties = new();
// some style attributes, such as borders or bgcolor, will convert this node to a framed container
protected bool renderAsFramed;
private HtmlBorder styleBorder;


public BlockElementExpression(IHtmlElement node, OpenXmlLeafElement? styleProperty) : base(node)
{
if (styleProperty is not null)
defaultStyleProperties = [styleProperty];
}
public BlockElementExpression(IHtmlElement node, params OpenXmlLeafElement[]? styleProperty) : base(node)
{
defaultStyleProperties = styleProperty;
}


/// <inheritdoc/>
public override IEnumerable<OpenXmlElement> Interpret (ParsingContext context)
{
var elements = base.Interpret(context);
var childElements = base.Interpret(context);

var bookmarkTarget = node.GetAttribute(InternalNamespaceUri, "bookmark");
if (bookmarkTarget is not null)
{
var bookmarkId = IncrementBookmarkId(context).ToString(CultureInfo.InvariantCulture);
var p = elements.First();
var p = childElements.First();
// need to be inserted after pPr to avoid schema warning
p.InsertAfter(new BookmarkStart() { Id = bookmarkId, Name = bookmarkTarget }, p.GetFirstChild<ParagraphProperties>());
p.AppendChild(new BookmarkEnd() { Id = bookmarkId });
}

return elements;
if (!renderAsFramed)
return childElements;

var paragraphs = childElements.OfType<Paragraph>();
if (!paragraphs.Any()) return childElements;

// if we have only 1 paragraph, just inline the styles
if (paragraphs.Count() == 1)
{
var p = paragraphs.First();

if (!styleBorder.IsEmpty && p.ParagraphProperties?.ParagraphBorders is null)
{
p.ParagraphProperties ??= new();
p.ParagraphProperties!.ParagraphBorders = new ParagraphBorders {
LeftBorder = Converter.ToBorder<LeftBorder>(styleBorder.Left),
RightBorder = Converter.ToBorder<RightBorder>(styleBorder.Right),
TopBorder = Converter.ToBorder<TopBorder>(styleBorder.Top),
BottomBorder = Converter.ToBorder<BottomBorder>(styleBorder.Bottom)
};
}

return childElements;
}

// if we have 2+ paragraphs, we will embed them inside a stylised table
return [CreateFrame(childElements)];
}

protected override IEnumerable<OpenXmlElement> Interpret (
Expand Down Expand Up @@ -136,17 +176,11 @@ protected override void ComposeStyles (ParsingContext context)
}


var styleBorder = styleAttributes.GetBorders();
styleBorder = styleAttributes.GetBorders();
if (!styleBorder.IsEmpty)
{
var borders = new ParagraphBorders {
LeftBorder = Converter.ToBorder<LeftBorder>(styleBorder.Left),
RightBorder = Converter.ToBorder<RightBorder>(styleBorder.Right),
TopBorder = Converter.ToBorder<TopBorder>(styleBorder.Top),
BottomBorder = Converter.ToBorder<BottomBorder>(styleBorder.Bottom)
};

paraProperties.ParagraphBorders = borders;
renderAsFramed = true;
runProperties.Border = null;
}

foreach (string className in node.ClassList)
Expand All @@ -159,8 +193,8 @@ protected override void ComposeStyles (ParsingContext context)
}
}

Margin margin = styleAttributes.GetMargin("margin");
Indentation? indentation = null;
var margin = styleAttributes.GetMargin("margin");
Indentation? indentation = null;
if (!margin.IsEmpty)
{
if (margin.Top.IsFixed || margin.Bottom.IsFixed)
Expand Down Expand Up @@ -236,6 +270,9 @@ protected override void ComposeStyles (ParsingContext context)
};
}
}

if (runProperties.Shading != null)
renderAsFramed = true;
}

/// <summary>
Expand Down Expand Up @@ -322,6 +359,43 @@ private static Paragraph CreateParagraph(ParsingContext context, IList<OpenXmlEl
return p;
}


/// <summary>
/// Group all the paragraph inside a framed table.
/// </summary>
private Table CreateFrame(IEnumerable<OpenXmlElement> childElements)
{
TableCell cell;
TableProperties tableProperties;
Table framedTable = new(
tableProperties = new TableProperties {
TableWidth = new() { Type = TableWidthUnitValues.Pct, Width = "5000" } // 100%
},
new TableGrid(
new GridColumn() { Width = "9442" }),
new TableRow(
cell = new TableCell(childElements)
)
);

if (!styleBorder.IsEmpty)
{
tableProperties.TableBorders = new TableBorders {
LeftBorder = Converter.ToBorder<LeftBorder>(styleBorder.Left),
RightBorder = Converter.ToBorder<RightBorder>(styleBorder.Right),
TopBorder = Converter.ToBorder<TopBorder>(styleBorder.Top),
BottomBorder = Converter.ToBorder<BottomBorder>(styleBorder.Bottom)
};
}

if (runProperties.Shading != null)
{
cell.TableCellProperties = new() { Shading = (Shading?) runProperties.Shading.Clone() };
}

return framedTable;
}

/// <summary>
/// Resolve the next available <see cref="BookmarkStart.Id"/> (they must be unique).
/// </summary>
Expand Down
Loading
Loading