Skip to content

Commit

Permalink
[+]: add missing CSS-Media-Queries from "setCSS()"
Browse files Browse the repository at this point in the history
  • Loading branch information
voku committed Feb 7, 2017
1 parent c0aad1e commit 60ad616
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 24 deletions.
79 changes: 58 additions & 21 deletions src/CssToInlineStyles.php
Expand Up @@ -69,78 +69,84 @@ class CssToInlineStyles
private static $styleCommentRegEx = '/\\/\\*.*\\*\\//sU';

/**
* The CSS to use
* The CSS to use.
*
* @var string
* @var string
*/
private $css;

/**
* Should the generated HTML be cleaned
* The CSS-Media-Queries to use.
*
* @var bool
* @var string
*/
private $css_media_queries;

/**
* Should the generated HTML be cleaned.
*
* @var bool
*/
private $cleanup = false;

/**
* The encoding to use.
*
* @var string
* @var string
*/
private $encoding = 'UTF-8';

/**
* The HTML to process
* The HTML to process.
*
* @var string
* @var string
*/
private $html;

/**
* Use inline-styles block as CSS
* Use inline-styles block as CSS.
*
* @var bool
*/
private $useInlineStylesBlock = false;

/**
* Use link block reference as CSS
* Use link block reference as CSS.
*
* @var bool
*/
private $loadCSSFromHTML = false;

/**
* Strip original style tags
* Strip original style tags.
*
* @var bool
*/
private $stripOriginalStyleTags = false;

/**
* Exclude conditional inline-style blocks
* Exclude conditional inline-style blocks.
*
* @var bool
*/
private $excludeConditionalInlineStylesBlock = true;

/**
* Exclude media queries from "$this->css" and keep media queries for inline-styles blocks
* Exclude media queries from "$this->css" and keep media queries for inline-styles blocks.
*
* @var bool
*/
private $excludeMediaQueries = true;

/**
* Exclude media queries from "$this->css" and keep media queries for inline-styles blocks
* Exclude media queries from "$this->css" and keep media queries for inline-styles blocks.
*
* @var bool
*/
private $excludeCssCharset = true;

/**
* Creates an instance, you could set the HTML and CSS here, or load it
* later.
* Creates an instance, you could set the HTML and CSS here, or load it later.
*
* @param null|string $html The HTML to process.
* @param null|string $css The CSS to use.
Expand All @@ -161,7 +167,7 @@ public function __construct($html = null, $css = null)
}

/**
* Set HTML to process
* Set HTML to process.
*
* @param string $html The HTML to process.
*
Expand All @@ -176,7 +182,7 @@ public function setHTML($html)
}

/**
* Set CSS to use
* Set CSS to use.
*
* @param string $css The CSS to use.
*
Expand All @@ -186,12 +192,15 @@ public function setCSS($css)
{
$this->css = (string)$css;

$this->css_media_queries = $this->getMediaQueries($css);

return $this;
}

/**
* Sort an array on the specificity element in an ascending way
* Lower specificity will be sorted to the beginning of the array
* Sort an array on the specificity element in an ascending way.
*
* INFO: Lower specificity will be sorted to the beginning of the array.
*
* @param Specificity[] $e1 The first element.
* @param Specificity[] $e2 The second element.
Expand Down Expand Up @@ -287,7 +296,18 @@ public function convert($outputXHTML = false, $libXMLExtraOptions = null, $path
}

// just regular HTML 4.01 as it should be used in newsletters
return $dom->html();
$html = $dom->html();

// add css media queries from "$this->setCSS()"
if (
$this->stripOriginalStyleTags === false
&&
$this->css_media_queries
) {
$html = str_ireplace('</head>', '<style type="text/css">' . "\n" . $this->css_media_queries . "\n" . '</styles>', $html);
}

return $html;
}

/**
Expand Down Expand Up @@ -445,6 +465,23 @@ private function stripeMediaQueries($css)
return (string)preg_replace(self::$cssMediaQueriesRegEx, '', $css);
}

/**
* get css media queries from the string
*
* @param string $css
*
* @return string
*/
private function getMediaQueries($css)
{
// remove comments previously to matching media queries
$css = preg_replace(self::$styleCommentRegEx, '', $css);

preg_match_all(self::$cssMediaQueriesRegEx, $css, $matches);

return implode("\n", $matches[0]);
}

/**
* remove charset from the string
*
Expand Down Expand Up @@ -608,7 +645,7 @@ private function createXPath(\DOMDocument $document, array $cssRules)
$originalStyle = $element->attributes->getNamedItem('style');

if ($originalStyle) {
$originalStyle = $originalStyle->value;
$originalStyle = (string)$originalStyle->value;
} else {
$originalStyle = '';
}
Expand Down
100 changes: 99 additions & 1 deletion tests/CssToInlineStylesTest.php
Expand Up @@ -4,6 +4,7 @@

use voku\CssToInlineStyles\CssToInlineStyles;
use voku\CssToInlineStyles\Exception;
use voku\helper\UTF8;

/**
* Class CssToInlineStylesTest
Expand Down Expand Up @@ -253,6 +254,7 @@ public function testCssShorthandProperties()
->setHTML($html)
->setCSS($css);
$actual = $cssToInlineStyles->convert();

self::assertSame($expected, $actual);
}

Expand All @@ -268,6 +270,7 @@ public function testDuplicateCssWithFoundation()
->setUseInlineStylesBlock(true)
->setHTML($html);
$actual = $cssToInlineStyles->convert();

self::assertSame($expected, $actual);
}

Expand All @@ -283,6 +286,7 @@ public function testCssBigFile()
->setHTML($html)
->setCSS($css);
$actual = $cssToInlineStyles->convert();

self::assertSame($expected, $actual);
}

Expand All @@ -302,6 +306,7 @@ public function testKeepMediaQuery()
->setHTML($html)
->setCSS($css);
$actual = $cssToInlineStyles->convert();

self::assertSame($expected, $actual);
}

Expand Down Expand Up @@ -911,7 +916,7 @@ public function testSpecialCharactersExplicit()
*/
protected function file_get_contents($filename)
{
$string = file_get_contents($filename);
$string = UTF8::file_get_contents($filename);

return $this->normalizeString($string);
}
Expand Down Expand Up @@ -968,4 +973,97 @@ public function testStyleTagsWithAttributeInHtml()

self::assertEquals($this->normalizeString($expected), $result);
}

public function testIssue25()
{
$css = '
*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
body, html {margin: 0;padding: 0;width: 100%;}
div.row {width: 100%;display: block;clear: both;}
div.col-25 { width: 25%;float: left; display: block;padding: 10px;}
div.content {width:100%; background: #eee;padding: 10px;}
@media only screen and (min-width: 360px) {
div.col-25 { width: 100%; float: left; display: block;padding: 10px;}
}
@media only screen and (min-width: 120px) {
div.col-25 { width: 100%; display: block; padding: 15px;}
}
';

$html = <<<HTML
<!DOCTYPE html>
<html>
<head>
<title>Testing</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="row">
<div class="col-25">
<div class="content">Hello World!</div>
</div>
<div class="col-25">
<div class="content">Hello World!</div>
</div>
<div class="col-25">
<div class="content">Hello World!</div>
</div>
<div class="col-25">
<div class="content">Hello World!</div>
</div>
</div>
</body>
</html>
HTML;

$expected = <<<EXPECTED
<!DOCTYPE html>
<html style="margin: 0; padding: 0; width: 100%;">
<head>
<title>Testing</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
@media only screen and (min-width: 360px) {
div.col-25 { width: 100%; float: left; display: block;padding: 10px;}
}
@media only screen and (min-width: 120px) {
div.col-25 { width: 100%; display: block; padding: 15px;}
}
</styles>
<body style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; margin: 0; padding: 0; width: 100%;">
<div class="row" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; clear: both; display: block; width: 100%;">
<div class="col-25" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; display: block; float: left; padding: 10px; width: 25%;">
<div class="content" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; background: #eee; padding: 10px; width: 100%;">Hello World!</div>
</div>
<div class="col-25" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; display: block; float: left; padding: 10px; width: 25%;">
<div class="content" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; background: #eee; padding: 10px; width: 100%;">Hello World!</div>
</div>
<div class="col-25" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; display: block; float: left; padding: 10px; width: 25%;">
<div class="content" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; background: #eee; padding: 10px; width: 100%;">Hello World!</div>
</div>
<div class="col-25" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; display: block; float: left; padding: 10px; width: 25%;">
<div class="content" style="-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; background: #eee; padding: 10px; width: 100%;">Hello World!</div>
</div>
</div>
</body>
</html>
EXPECTED;

$cssToInlineStyles = new CssToInlineStyles();

$result = $cssToInlineStyles
->setExcludeMediaQueries(false)
->setHTML($html)
->setCSS($css)
->convert();

self::assertEquals($this->normalizeString($expected), $this->normalizeString($result));
}
}

0 comments on commit 60ad616

Please sign in to comment.