Skip to content

Commit

Permalink
[FEATURE] Allow user to define media types to keep
Browse files Browse the repository at this point in the history
Also keep the print media type by default.

Fixes #68
FIxes #178
  • Loading branch information
Renkas authored and oliverklee committed Jul 6, 2015
1 parent 7593bb1 commit ae7fb74
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 6 deletions.
44 changes: 40 additions & 4 deletions Classes/Emogrifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ class Emogrifier
*/
private $unprocessableHtmlTags = array('wbr');

/**
* @var bool[]
*/
private $allowedMediaTypes = array('all' => true, 'screen' => true, 'print' => true);

/**
* @var array[]
*/
Expand Down Expand Up @@ -407,6 +412,32 @@ public function removeUnprocessableHtmlTag($tagName)
}
}

/**
* Marks a media query type to keep.
*
* @param string $mediaName the media type name, e.g., "braille"
*
* @return void
*/
public function addAllowedMediaType($mediaName)
{
$this->allowedMediaTypes[$mediaName] = true;
}

/**
* Drops a media query type from the allowed list.
*
* @param string $mediaName the tag name, e.g., "braille"
*
* @return void
*/
public function removeAllowedMediaType($mediaName)
{
if (isset($this->allowedMediaTypes[$mediaName])) {
unset($this->allowedMediaTypes[$mediaName]);
}
}

/**
* This removes styles from your email that contain display:none.
* We need to look for display:none, but we need to do a case-insensitive search. Since DOMDocument only
Expand Down Expand Up @@ -615,8 +646,13 @@ private function splitCssAndMediaQuery($css)
{
$media = '';

$css = preg_replace_callback(
'#@media\\s+(?:only\\s)?(?:[\\s{\\(]|screen|all)\\s?[^{]+{.*}\\s*}\\s*#misU',
$mediaTypesExpression = '';
if (!empty($this->allowedMediaTypes)) {
$mediaTypesExpression = '|' . implode('|', array_keys($this->allowedMediaTypes));
}

$cssForAllowedMediaTypes = preg_replace_callback(
'#@media\\s+(?:only\\s)?(?:[\\s{\\(]' . $mediaTypesExpression . ')\\s?[^{]+{.*}\\s*}\\s*#misU',
function ($matches) use (&$media) {
$media .= $matches[0];
},
Expand All @@ -640,9 +676,9 @@ function ($matches) use (&$media) {
);

// clean CSS before output
$css = preg_replace($search, $replace, $css);
$cleanedCss = preg_replace($search, $replace, $cssForAllowedMediaTypes);

return array('css' => $css, 'media' => $media);
return array('css' => $cleanedCss, 'media' => $media);
}

/**
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ calling the `emogrify` method:
* `$emogrifier->disableInvisibleNodeRemoval()` - By default, Emogrifier removes
elements from the DOM that have the style attribute `display: none;`. If
you would like to keep invisible elements in the DOM, use this option.
* `$emogrifier->addAllowedMediaType(string $mediaName)` - By default, Emogrifier
will keep only media types `all`, `screen` and `print`. If you want to keep
some others, you can use this method to define them.
* `$emogrifier->removeAllowedMediaType(string $mediaName)` - You can use this
method to remove media types that Emogrifier keeps.


## Installing with Composer
Expand Down
39 changes: 37 additions & 2 deletions Tests/Unit/EmogrifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,6 @@ public function unneededCssThingsDataProvider()
'style in "braille" media type rule' => array('@media braille {p {color: #000;}}', '#000'),
'style in "embossed" media type rule' => array('@media embossed {p {color: #000;}}', '#000'),
'style in "handheld" media type rule' => array('@media handheld {p {color: #000;}}', '#000'),
'style in "print" media type rule' => array('@media print {p {color: #000;}}', '#000'),
'style in "projection" media type rule' => array('@media projection {p {color: #000;}}', '#000'),
'style in "speech" media type rule' => array('@media speech {p {color: #000;}}', '#000'),
'style in "tty" media type rule' => array('@media tty {p {color: #000;}}', '#000'),
Expand Down Expand Up @@ -939,6 +938,7 @@ public function mediaRulesDataProvider()
'style in "only screen" media type rule' => array('@media only screen {p {color: #000;}}'),
'style in media type rule' => array('@media {p {color: #000;}}'),
'style in "screen" media type rule' => array('@media screen {p {color: #000;}}'),
'style in "print" media type rule' => array('@media print {p {color: #000;}}'),
'style in "all" media type rule' => array('@media all {p {color: #000;}}'),
);
}
Expand All @@ -962,6 +962,42 @@ public function emogrifyKeepsMediaRules($css)
);
}

/**
* @test
*/
public function removeAllowedMediaTypeRemovesStylesForTheGivenMediaType()
{
$css = '@media screen { html {} }';

$html = $this->html5DocumentType . self::LF . '<html></html>';
$this->subject->setHtml($html);
$this->subject->setCss($css);
$this->subject->removeAllowedMediaType('screen');

self::assertNotContains(
$css,
$this->subject->emogrify()
);
}

/**
* @test
*/
public function addAllowedMediaTypeKeepsStylesForTheGivenMediaType()
{
$css = '@media braille { html {} }';

$html = $this->html5DocumentType . self::LF . '<html></html>';
$this->subject->setHtml($html);
$this->subject->setCss($css);
$this->subject->addAllowedMediaType('braille');

self::assertContains(
$css,
$this->subject->emogrify()
);
}

/**
* @test
*/
Expand Down Expand Up @@ -1111,7 +1147,6 @@ public function invalidMediaPreserveDataProvider()
'style in "braille" type rule' => array('@media braille { h1 { color:red; } }'),
'style in "embossed" type rule' => array('@media embossed { h1 { color:red; } }'),
'style in "handheld" type rule' => array('@media handheld { h1 { color:red; } }'),
'style in "print" type rule' => array('@media print { h1 { color:red; } }'),
'style in "projection" type rule' => array('@media projection { h1 { color:red; } }'),
'style in "speech" type rule' => array('@media speech { h1 { color:red; } }'),
'style in "tty" type rule' => array('@media tty { h1 { color:red; } }'),
Expand Down

0 comments on commit ae7fb74

Please # to comment.