Skip to content

Commit

Permalink
Merge pull request #275 from MIG-Global/master
Browse files Browse the repository at this point in the history
  • Loading branch information
martinnormark authored Nov 2, 2021
2 parents 1756f74 + 22ad181 commit 54d6dbf
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 12 deletions.
20 changes: 20 additions & 0 deletions PreMailer.Net/PreMailer.Net.Tests/PreMailerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,26 @@ public void MoveCssInline_KeepStyleElementsIgnoreElementsMatchesStyleElement_Doe
Assert.Contains("<style id=\"ignore\" type=\"text/css\">", premailedOutput.Html);
}

[Fact]
public void MoveCssInline_PreserveMediaQueries_RemovesStyleElementsWithoutMediaQueries()
{
string input = "<html><head><style>div { width: 42px; }</style></head><body><div>test</div></body></html>";

var premailedOutput = PreMailer.MoveCssInline(input, removeStyleElements: true, preserveMediaQueries: true);

Assert.DoesNotContain("<style>", premailedOutput.Html);
}

[Fact]
public void MoveCssInline_PreserveMediaQueries_PreservesStyleElementsWithMediaQueries()
{
string input = "<html><head><style>div { width: 42px; } @media (max-width: 250px) { div { width: 20px; } }</style></head><body><div>test</div></body></html>";

var premailedOutput = PreMailer.MoveCssInline(input, removeStyleElements: true, preserveMediaQueries: true);

Assert.Contains("<style>@media (max-width: 250px) { div { width: 20px; } }</style>", premailedOutput.Html);
}

[Fact]
public void MoveCssInline_MultipleSelectors_HonorsIndividualSpecificity()
{
Expand Down
15 changes: 15 additions & 0 deletions PreMailer.Net/PreMailer.Net/CssParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,20 @@ private static string CleanupMediaQueries(string s)
{
return MediaQueryRegex.Replace(s, m => SupportedMediaQueriesRegex.IsMatch(m.Groups["query"].Value.Trim()) ? m.Groups["styles"].Value.Trim() : string.Empty);
}

public static IEnumerable<string> GetUnsupportedMediaQueries(string s)
{
if (string.IsNullOrWhiteSpace(s))
{
yield break;
}
foreach (Match match in MediaQueryRegex.Matches(s))
{
if (!SupportedMediaQueriesRegex.IsMatch(match.Value))
{
yield return match.Value;
}
}
}
}
}
44 changes: 32 additions & 12 deletions PreMailer.Net/PreMailer.Net/PreMailer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ public PreMailer(Stream stream, Uri baseUri = null)
/// <param name="css">A string containing a style-sheet for inlining.</param>
/// <param name="stripIdAndClassAttributes">True to strip ID and class attributes</param>
/// <param name="removeComments">True to remove comments, false to leave them intact</param>
/// <param name="preserveMediaQueries">If set to true and removeStyleElements is true, it will instead preserve unsupported media queries in the style node and remove the other css, instead of removing the whole style node</param>
/// <returns>Returns the html input, with styles moved to inline attributes.</returns>
public static InlineResult MoveCssInline(string html, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null)
public static InlineResult MoveCssInline(string html, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null, bool preserveMediaQueries = false)
{
return new PreMailer(html).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter);
return new PreMailer(html).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter, preserveMediaQueries);
}

/// <summary>
Expand All @@ -88,10 +89,11 @@ public static InlineResult MoveCssInline(string html, bool removeStyleElements =
/// <param name="css">A string containing a style-sheet for inlining.</param>
/// <param name="stripIdAndClassAttributes">True to strip ID and class attributes</param>
/// <param name="removeComments">True to remove comments, false to leave them intact</param>
/// <param name="preserveMediaQueries">If set to true and removeStyleElements is true, it will instead preserve unsupported media queries in the style node and remove the other css, instead of removing the whole style node</param>
/// <returns>Returns the html input, with styles moved to inline attributes.</returns>
public static InlineResult MoveCssInline(Stream stream, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null)
public static InlineResult MoveCssInline(Stream stream, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null, bool preserveMediaQueries = false)
{
return new PreMailer(stream).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter);
return new PreMailer(stream).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter, preserveMediaQueries);
}

/// <summary>
Expand All @@ -105,10 +107,11 @@ public static InlineResult MoveCssInline(Stream stream, bool removeStyleElements
/// <param name="css">A string containing a style-sheet for inlining.</param>
/// <param name="stripIdAndClassAttributes">True to strip ID and class attributes</param>
/// <param name="removeComments">True to remove comments, false to leave them intact</param>
/// <param name="preserveMediaQueries">If set to true and removeStyleElements is true, it will instead preserve unsupported media queries in the style node and remove the other css, instead of removing the whole style node</param>
/// <returns>Returns the html input, with styles moved to inline attributes.</returns>
public static InlineResult MoveCssInline(Uri baseUri, string html, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null)
public static InlineResult MoveCssInline(Uri baseUri, string html, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null, bool preserveMediaQueries = false)
{
return new PreMailer(html, baseUri).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter);
return new PreMailer(html, baseUri).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter, preserveMediaQueries);
}

/// <summary>
Expand All @@ -122,10 +125,11 @@ public static InlineResult MoveCssInline(Uri baseUri, string html, bool removeSt
/// <param name="css">A string containing a style-sheet for inlining.</param>
/// <param name="stripIdAndClassAttributes">True to strip ID and class attributes</param>
/// <param name="removeComments">True to remove comments, false to leave them intact</param>
/// <param name="preserveMediaQueries">If set to true and removeStyleElements is true, it will instead preserve unsupported media queries in the style node and remove the other css, instead of removing the whole style node</param>
/// <returns>Returns the html input, with styles moved to inline attributes.</returns>
public static InlineResult MoveCssInline(Uri baseUri, Stream stream, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null)
public static InlineResult MoveCssInline(Uri baseUri, Stream stream, bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null, bool preserveMediaQueries = false)
{
return new PreMailer(stream, baseUri).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter);
return new PreMailer(stream, baseUri).MoveCssInline(removeStyleElements, ignoreElements, css, stripIdAndClassAttributes, removeComments, customFormatter, preserveMediaQueries);
}

/// <summary>
Expand All @@ -136,8 +140,9 @@ public static InlineResult MoveCssInline(Uri baseUri, Stream stream, bool remove
/// <param name="css">A string containing a style-sheet for inlining.</param>
/// <param name="stripIdAndClassAttributes">True to strip ID and class attributes</param>
/// <param name="removeComments">True to remove comments, false to leave them intact</param>
/// <param name="preserveMediaQueries">If set to true and removeStyleElements is true, it will instead preserve unsupported media queries in the style node and remove the other css, instead of removing the whole style node</param>
/// <returns>Returns the html input, with styles moved to inline attributes.</returns>
public InlineResult MoveCssInline(bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null)
public InlineResult MoveCssInline(bool removeStyleElements = false, string ignoreElements = null, string css = null, bool stripIdAndClassAttributes = false, bool removeComments = false, IMarkupFormatter customFormatter = null, bool preserveMediaQueries = false)
{
// Store the variables used for inlining the CSS
_removeStyleElements = removeStyleElements;
Expand All @@ -155,7 +160,7 @@ public InlineResult MoveCssInline(bool removeStyleElements = false, string ignor

if (_removeStyleElements)
{
RemoveStyleElements(cssSourceNodes);
RemoveStyleElements(cssSourceNodes, preserveMediaQueries);
RemoveStyleElements(cssLinkNodes);
}

Expand Down Expand Up @@ -317,11 +322,26 @@ private IEnumerable<IElement> CssLinkNodes()
}


private void RemoveStyleElements(IEnumerable<IElement> cssSourceNodes)
private void RemoveStyleElements(IEnumerable<IElement> cssSourceNodes, bool preserveMediaQueries = false)
{
foreach (var node in cssSourceNodes)
{
node.Remove();
if (preserveMediaQueries)
{
var unsupportedMediaQueries = CssParser.GetUnsupportedMediaQueries(node.InnerHtml);
if (unsupportedMediaQueries.Any())
{
node.InnerHtml = $"{string.Join("\n", unsupportedMediaQueries)}";
}
else
{
node.Remove();
}
}
else
{
node.Remove();
}
}
}

Expand Down

0 comments on commit 54d6dbf

Please sign in to comment.