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.2 #182

Merged
merged 14 commits into from
Dec 11, 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
1 change: 0 additions & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ on:
- 'docs/**'
- '**/*.md'
pull_request:
branches: [ "dev" ]

jobs:
net8:
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 3.2.2

- Supports a feature to disable heading numbering #175
- Support center image with margin auto #171
- Support deprecrated align attribute for block #171
- Fix parsing of style attribute with a key with no value
- Improve parsing of style attribute to avoid an extra call to HtmlDecode
- Extend support of nested list for non-W3C compliant html #173
- Change way to apply table 100% width
- Allow to apply percentage widths cells

## 3.2.1

- Fix indentation of numbering list #166
Expand Down
58 changes: 29 additions & 29 deletions HtmlToOpenXml.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,33 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlToOpenXml.Tests", "test\HtmlToOpenXml.Tests\HtmlToOpenXml.Tests.csproj", "{CA0A68E0-45A0-4A01-A061-F951D93D6906}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Release|Any CPU.Build.0 = Release|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Release|Any CPU.Build.0 = Release|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EF700F30-C9BB-49A6-912C-E3B77857B514} = {58520A98-BA53-4BA4-AAE3-786AA21331D6}
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F} = {84EA02ED-2E97-47D2-992E-32CC104A3A7A}
{CA0A68E0-45A0-4A01-A061-F951D93D6906} = {84EA02ED-2E97-47D2-992E-32CC104A3A7A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {14EE1026-6507-4295-9FEE-67A55C3849CE}
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF700F30-C9BB-49A6-912C-E3B77857B514}.Release|Any CPU.Build.0 = Release|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F}.Release|Any CPU.Build.0 = Release|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA0A68E0-45A0-4A01-A061-F951D93D6906}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EF700F30-C9BB-49A6-912C-E3B77857B514} = {58520A98-BA53-4BA4-AAE3-786AA21331D6}
{A1ECC760-B9F7-4A00-AF5F-568B5FD6F09F} = {84EA02ED-2E97-47D2-992E-32CC104A3A7A}
{CA0A68E0-45A0-4A01-A061-F951D93D6906} = {84EA02ED-2E97-47D2-992E-32CC104A3A7A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {14EE1026-6507-4295-9FEE-67A55C3849CE}
EndGlobalSection
EndGlobal
2 changes: 1 addition & 1 deletion examples/Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ static void AssertThatOpenXmlDocumentIsValid(WordprocessingDocument wpDoc)
Console.ReadLine();
}
}
}
}
134 changes: 80 additions & 54 deletions examples/Demo/Resources/CompleteRunTest.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@
<title></title>
</head>
<body>

<table style="width: 100%; border-collapse: collapse; margin: 20px auto; border: 1px solid #ccc;">
<tr style="background-color: #f4f4f4; text-align: left;">
<th style="width: 10%; border: 1px solid #ccc; padding: 8px;">Column 1</th>
<th style="width: 60%; border: 1px solid #ccc; padding: 8px;">Column 2</th>
<th style="width: 30%; border: 1px solid #ccc; padding: 8px;">Column 3</th>
</tr>
<tr>
<td style="width: 10%; border: 1px solid #ccc; padding: 8px;">Row 1, Cell 1</td>
<td style="width: 60%; border: 1px solid #ccc; padding: 8px;">Row 1, Cell 2</td>
<td style="width: 30%; border: 1px solid #ccc; padding: 8px;">Row 1, Cell 3</td>
</tr>
<tr>
<td style="width: 10%; border: 1px solid #ccc; padding: 8px;">Row 2, Cell 1</td>
<td style="width: 60%; border: 1px solid #ccc; padding: 8px;">Row 2, Cell 2</td>
<td style="width: 30%; border: 1px solid #ccc; padding: 8px;">Row 2, Cell 3</td>
</tr>
</table>

<h1></h1>
<h1>Heading 1</h1>
<h2>Heading 2</h2>
Expand All @@ -15,8 +34,11 @@ <h5>Heading 5</h5>
<span style="font-variant: small-caps"> Small caps</span><br />
<strike>Strike</strike> <span style="text-decoration: line-through"> Line Through</span> <span style="text-decoration: overline"> Overline</span> <span style="text-decoration: underline"> Underline</span><br />
<b> Bold</b><br />
<span>This is a <b>bold
</b>text</span>
<span>
This is a <b>
bold
</b>text
</span>
<span style="font-weight: bold">Bold</span><br />
<span style="font-weight: bolder">Bolder</span><br />
<span style="font-weight: lighter">Lighter</span><br />
Expand Down Expand Up @@ -47,7 +69,8 @@ <h5>Heading 5</h5>
<a href="www.github.com"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" /></a>

<!-- multiline images -->
<p><img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8l
<p>
<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8l
JCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/wAALCABVAEABAREA/8QAHwAA
AQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQR
BRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RF
Expand Down Expand Up @@ -88,7 +111,8 @@ <h5>Heading 5</h5>
OfDEXhz/AIRbxtAkV1pYNrJHNC0qSbPlDKQDg8e3tVD4Q6BKPGmp67Y2lxbaJ5ckVo04IMgZ
1KjnqAByfXFezMiv95Q2PUZoCKOigY9BSkA9QDjmgqGBDAEHsaia0tnQxtbxMjdVKAg0W9pb
Wilba3ihB6iNAufyoltLaZw8tvFIw6FkBNSgADA4FLRRRRRRRX//2Q==
"></p>
">
</p>

<img src="https://www.w3schools.com/tags/smiley.gif" alt="Smiley face" width="42" height="42">

Expand All @@ -102,79 +126,81 @@ <h5>Heading 5</h5>
<br />


<blockquote cite="http://www.worldwildlife.org/who/index.html">
For 50 years, <b>WWF</b> has been protecting the future of nature. The world's leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United States and close to 5 million globally.
</blockquote>
<blockquote cite="http://www.worldwildlife.org/who/index.html">
For 50 years, <b>WWF</b> has been protecting the future of nature. The world's leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United States and close to 5 million globally.
</blockquote>

<br class="ibp-rteFontSize-5"/><span style="font-size: 16.9px">My Text </span>
<br class="ibp-rteFontSize-5" /><span style="font-size: 16.9px">My Text </span>

<p>An ordered list:</p>
<p>An ordered list:</p>
<ol>
<li>Coffee</li>
<li>Tea</li>
<li>Milk
<ul>
<li>Coffee</li>
<li>Tea
<ol>
<li>Earl Grey</li>
<li>Green</li>
<li>Rosboh</li>
</ol>
</li>
<li>Milk</li>
</ul>
</li>
<li>Wine</li>
<li>Coffee</li>
<li>Tea</li>
<li>
Milk
<ul>
<li>Coffee</li>
<li>
Tea
<ol>
<li>Earl Grey</li>
<li>Green</li>
<li>Rosboh</li>
</ol>
</li>
<li>Milk</li>
</ul>
</li>
<li>Wine</li>
</ol>

<table border=1><tr><td>Inside table</td></tr></table>
<hr />
<p>delta parameter (<span style='font-family:Symbol'>d</span>)</p>
Looks how cool is <font size="x-large" color="maroon"><b>Open Xml</b></font>.
<hr />
Now with <font color="red"><u>HtmlToOpenXml</u></font>, it never been so easy to convert html.
<p>
If you like it, add me a rating on <a href="https://github.com/onizet/html2openxml">github</a>
</p>

simple text
<div style="page-orientation: landscape; page-break-before: always">
Hello !
je suis du texte
<span style="font-style: oblique">écrit en oblique.</span>

<pre lang="fr-FR" class="c#"> public void SetContentType(System.Web.HttpRequest request, System.Web.HttpResponse response, String reportName)
<table border=1><tr><td>Inside table</td></tr></table>
<hr />
<p>delta parameter (<span style='font-family:Symbol'>d</span>)</p>
Looks how cool is <font size="x-large" color="maroon"><b>Open Xml</b></font>.
<hr />
Now with <font color="red"><u>HtmlToOpenXml</u></font>, it never been so easy to convert html.
<p>
If you like it, add me a rating on <a href="https://github.com/onizet/html2openxml">github</a>
</p>

simple text
<div style="page-orientation: landscape; page-break-before: always">
Hello !
je suis du texte
<span style="font-style: oblique">écrit en oblique.</span>

<pre lang="fr-FR" class="c#"> public void SetContentType(System.Web.HttpRequest request, System.Web.HttpResponse response, String reportName)
{
if (request.Browser.Browser.Contains(&quot;IE&quot;))
{
<span style="color:Green">// Replace the %20 to obtain a clean name when saving the file from Word.</span>
<span style="color:Green">// Replace the %20 to obtain a clean name when saving the file from Word.</span>
encodedFilename =
Uri.EscapeDataString(Path.GetFileNameWithoutExtension(encodedFilename)).Replace(&quot;%20&quot;, &quot; &quot;)
+ Path.GetExtension(encodedFilename);
}
}
</pre>
<hr/>
<pre>
<hr />
<pre>
Some &lt;Pre&gt; starting one
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>
<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">
<!--<div style="page-break-before: always">
New page
</div>-->
</body>
Expand Down
11 changes: 2 additions & 9 deletions src/Html2OpenXml/Collections/HtmlAttributeCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ namespace HtmlToOpenXml;
/// </summary>
sealed class HtmlAttributeCollection
{
private static readonly Regex stripStyleAttributesRegex = new(@"(?<name>.+?):\s*(?<val>[^;]+);*\s*");

private static readonly Regex stripStyleAttributesRegex = new(@"(?<name>[^;\s]+)\s?(&\#58;|:)\s?(?<val>[^;&]+)\s?(;|&\#59;)*");
private readonly Dictionary<string, string> attributes = [];


Expand All @@ -37,13 +36,7 @@ public static HtmlAttributeCollection ParseStyle(string? htmlTag)

// Encoded ':' and ';' characters are valid for browser but not handled by the regex (bug #13812 reported by robin391)
// ex= <span style="text-decoration&#58;underline&#59;color:red">
MatchCollection matches = stripStyleAttributesRegex.Matches(
#if NET5_0_OR_GREATER
System.Web.HttpUtility.HtmlDecode(htmlTag)
#else
HttpUtility.HtmlDecode(htmlTag)
#endif
);
MatchCollection matches = stripStyleAttributesRegex.Matches(htmlTag);
foreach (Match m in matches)
collection.attributes[m.Groups["name"].Value] = m.Groups["val"].Value;

Expand Down
4 changes: 2 additions & 2 deletions src/Html2OpenXml/Expressions/BlockElementExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ protected override void ComposeStyles (ParsingContext context)
};
}

var attrValue = styleAttributes!["text-align"];
JustificationValues? align = Converter.ToParagraphAlign(attrValue);
JustificationValues? align = Converter.ToParagraphAlign(styleAttributes!["text-align"]);
if (!align.HasValue) align = Converter.ToParagraphAlign(node.GetAttribute("align"));
if (align.HasValue)
{
paraProperties.Justification = new() { Val = align };
Expand Down
2 changes: 1 addition & 1 deletion src/Html2OpenXml/Expressions/HyperlinkExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public override IEnumerable<OpenXmlElement> Interpret (ParsingContext context)
h = new Hyperlink() { History = true, Anchor = "_top" };
}
// is it an anchor?
else if (!context.Converter.ExcludeLinkAnchor && linkNode.Hash.Length > 1 && linkNode.Hash[0] == '#')
else if (context.Converter.SupportsAnchorLinks && linkNode.Hash.Length > 1 && linkNode.Hash[0] == '#')
{
h = new Hyperlink(
) { History = true, Anchor = linkNode.Hash.Substring(1) };
Expand Down
Loading
Loading