Skip to content

Header and Footer support #163

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

Merged
merged 8 commits into from
Sep 21, 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
9 changes: 7 additions & 2 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.CompleteRunTest.html");
string html = ResourceHelper.GetString("Resources.Document.html");
if (File.Exists(filename)) File.Delete(filename);

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

HtmlConverter converter = new HtmlConverter(mainPart);
// HeaderPart headerPart = mainPart.AddNewPart<HeaderPart>();
//FooterPart footerPart = mainPart.AddNewPart<FooterPart>();
converter.RenderPreAsTable = true;
Body body = mainPart.Document.Body;

await converter.ParseHtml(html);
await converter.ParseHeader(@"<a href=""www.github.com"">
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="" alt=""Red dot"" /> Red Dot</a>");

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

AssertThatOpenXmlDocumentIsValid(package);
Expand Down
3 changes: 2 additions & 1 deletion src/Html2OpenXml/Expressions/AbbreviationExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ public override IEnumerable<OpenXmlElement> Interpret(ParsingContext context)
var childElements = base.Interpret(context);

// Transform the inline acronym/abbreviation to a reference to a foot note.
// Footnote or endnote are invalid inside header and footer
string? description = node.Title;
if (string.IsNullOrEmpty(description))
if (string.IsNullOrEmpty(description) || context.HostingPart is not MainDocumentPart)
return childElements;

string runStyle;
Expand Down
9 changes: 7 additions & 2 deletions src/Html2OpenXml/Expressions/BlockQuoteExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Linq;
using AngleSharp.Html.Dom;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace HtmlToOpenXml.Expressions;
Expand All @@ -26,15 +27,19 @@ sealed class BlockQuoteExpression(IHtmlElement node) : BlockElementExpression(no
/// <inheritdoc/>
public override IEnumerable<OpenXmlElement> Interpret(ParsingContext context)
{
string? description = node.GetAttribute("cite");

var childElements = base.Interpret(context);
if (!childElements.Any())
return [];

// Footnote or endnote are invalid inside header and footer
if (context.HostingPart is not MainDocumentPart)
return childElements;

// Transform the inline acronym/abbreviation to a reference to a foot note.
if (childElements.First() is Paragraph paragraph)
{
string? description = node.GetAttribute("cite");

paragraph.ParagraphProperties ??= new();
if (paragraph.ParagraphProperties.ParagraphStyleId is null)
paragraph.ParagraphProperties.ParagraphStyleId =
Expand Down
11 changes: 7 additions & 4 deletions src/Html2OpenXml/Expressions/BodyExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using AngleSharp.Dom;
using AngleSharp.Html.Dom;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace HtmlToOpenXml.Expressions;
Expand All @@ -35,17 +36,19 @@ protected override void ComposeStyles(ParsingContext context)
{
base.ComposeStyles(context);

var mainPart = context.MainPart;

// Unsupported W3C attribute but claimed by users. Specified at <body> level, the page
// orientation is applied on the whole document
string? attr = styleAttributes!["page-orientation"];
if (attr != null)
{
PageOrientationValues orientation = Converter.ToPageOrientation(attr);

var sectionProperties = context.MainPart.Document.Body!.GetFirstChild<SectionProperties>();
var sectionProperties = mainPart.Document.Body!.GetFirstChild<SectionProperties>();
if (sectionProperties == null || sectionProperties.GetFirstChild<PageSize>() == null)
{
context.MainPart.Document.Body.Append(ChangePageOrientation(orientation));
mainPart.Document.Body.Append(ChangePageOrientation(orientation));
}
else
{
Expand All @@ -61,10 +64,10 @@ protected override void ComposeStyles(ParsingContext context)

if (paraProperties.BiDi is not null)
{
var sectionProperties = context.MainPart.Document.Body!.GetFirstChild<SectionProperties>();
var sectionProperties = mainPart.Document.Body!.GetFirstChild<SectionProperties>();
if (sectionProperties == null || sectionProperties.GetFirstChild<PageSize>() == null)
{
context.MainPart.Document.Body.Append(sectionProperties = new());
mainPart.Document.Body.Append(sectionProperties = new());
}

sectionProperties.AddChild(paraProperties.BiDi.CloneNode(true));
Expand Down
9 changes: 6 additions & 3 deletions src/Html2OpenXml/Expressions/HyperlinkExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Linq;
using AngleSharp.Html.Dom;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace HtmlToOpenXml.Expressions;
Expand Down Expand Up @@ -42,8 +43,10 @@ public override IEnumerable<OpenXmlElement> Interpret (ParsingContext context)
// Let's see whether the link tag include an image inside its body.
// If so, the Hyperlink OpenXmlElement is lost and we'll keep only the images
// and applied a HyperlinkOnClick attribute.
var imagesInLink = childElements.Where(e => e.HasChild<Drawing>());
if (imagesInLink.Any())
IEnumerable<OpenXmlElement> imagesInLink;
// Clickable image is only supported in body but not in header/footer
if (context.HostingPart is MainDocumentPart &&
(imagesInLink = childElements.Where(e => e.HasChild<Drawing>())).Any())
{
foreach (var img in imagesInLink)
{
Expand Down Expand Up @@ -100,7 +103,7 @@ public override IEnumerable<OpenXmlElement> Interpret (ParsingContext context)
// ensure the links does not start with javascript:
else if (AngleSharpExtensions.TryParseUrl(att, UriKind.Absolute, out var uri))
{
var extLink = context.MainPart.AddHyperlinkRelationship(uri!, true);
var extLink = context.HostingPart.AddHyperlinkRelationship(uri!, true);

h = new Hyperlink(
) { History = true, Id = extLink.Id };
Expand Down
2 changes: 1 addition & 1 deletion src/Html2OpenXml/Expressions/Image/ImageExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class ImageExpression(IHtmlImageElement node) : ImageExpressionBase(node)

var (imageObjId, drawingObjId) = IncrementDrawingObjId(context);

HtmlImageInfo? iinfo = context.Converter.ImagePrefetcher.Download(src, CancellationToken.None)
HtmlImageInfo? iinfo = context.ImageLoader.Download(src, CancellationToken.None)
.ConfigureAwait(false).GetAwaiter().GetResult();

if (iinfo == null)
Expand Down
8 changes: 5 additions & 3 deletions src/Html2OpenXml/Expressions/Image/ImageExpressionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

using a = DocumentFormat.OpenXml.Drawing;
Expand Down Expand Up @@ -85,10 +86,11 @@ internal static (uint imageObjId, uint drawingObjId) IncrementDrawingObjId(Parsi
drawingObjId ??= 1; // 1 is the minimum ID set by MS Office.
imageObjId ??= 1;

var mainPart = context.MainPart;
foreach (var part in new[] {
context.MainPart.Document.Body!.Descendants<Drawing>(),
context.MainPart.HeaderParts.Where(f => f.Header != null).SelectMany(f => f.Header.Descendants<Drawing>()),
context.MainPart.FooterParts.Where(f => f.Footer != null).SelectMany(f => f.Footer.Descendants<Drawing>())
mainPart.Document.Body!.Descendants<Drawing>(),
mainPart.HeaderParts.Where(f => f.Header != null).SelectMany(f => f.Header.Descendants<Drawing>()),
mainPart.FooterParts.Where(f => f.Footer != null).SelectMany(f => f.Footer.Descendants<Drawing>())
})
foreach (Drawing d in part)
{
Expand Down
Loading
Loading