Completed
Push — master ( d4a5f8...28ae2a )
by Lars
02:58
created

CssToInlineStyles::doCleanup()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 27
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 3

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 27
ccs 14
cts 14
cp 1
rs 8.8571
cc 3
eloc 12
nc 4
nop 1
crap 3
1
<?php
2
namespace voku\CssToInlineStyles;
3
4
use Symfony\Component\CssSelector\CssSelectorConverter;
5
use Symfony\Component\CssSelector\Exception\ExceptionInterface;
6
7
/**
8
 * CSS to Inline Styles class
9
 *
10
 * @author     Tijs Verkoyen <[email protected]>
11
 */
12
class CssToInlineStyles
13
{
14
15
  /**
16
   * regular expression: css media queries
17
   *
18
   * @var string
19
   */
20
  private static $cssMediaQueriesRegEx = '#@media\\s+(?:only\\s)?(?:[\\s{\\(]|screen|all)\\s?[^{]+{.*}\\s*}\\s*#misU';
21
22
  /**
23
   * regular expression: css charset
24
   *
25
   * @var string
26
   */
27
  private static $cssCharsetRegEx = '/@charset [\'"][^\'"]+[\'"];/i';
28
29
30
  /**
31
   * regular expression: conditional inline style tags
32
   *
33
   * @var string
34
   */
35
  private static $excludeConditionalInlineStylesBlockRegEx = '/<!--.*<style.*?-->/is';
36
37
  /**
38
   * regular expression: inline style tags
39
   *
40
   * @var string
41
   */
42
  private static $styleTagRegEx = '|<style(.*)>(.*)</style>|isU';
43
44
  /**
45
   * regular expression: css-comments
46
   *
47
   * @var string
48
   */
49
  private static $styleCommentRegEx = '/\\/\\*.*\\*\\//sU';
50
51
  /**
52
   * The CSS to use
53
   *
54
   * @var  string
55
   */
56
  private $css;
57
58
  /**
59
   * Should the generated HTML be cleaned
60
   *
61
   * @var  bool
62
   */
63
  private $cleanup = false;
64
65
  /**
66
   * The encoding to use.
67
   *
68
   * @var  string
69
   */
70
  private $encoding = 'UTF-8';
71
72
  /**
73
   * The HTML to process
74
   *
75
   * @var  string
76
   */
77
  private $html;
78
79
  /**
80
   * Use inline-styles block as CSS
81
   *
82
   * @var bool
83
   */
84
  private $useInlineStylesBlock = false;
85
86
  /**
87
   * Use link block reference as CSS
88
   *
89
   * @var bool
90
   */
91
  private $loadCSSFromHTML = false;
92
93
  /**
94
   * Strip original style tags
95
   *
96
   * @var bool
97
   */
98
  private $stripOriginalStyleTags = false;
99
100
  /**
101
   * Exclude conditional inline-style blocks
102
   *
103
   * @var bool
104
   */
105
  private $excludeConditionalInlineStylesBlock = true;
106
107
  /**
108
   * Exclude media queries from "$this->css" and keep media queries for inline-styles blocks
109
   *
110
   * @var bool
111
   */
112
  private $excludeMediaQueries = true;
113
114
  /**
115
   * Exclude media queries from "$this->css" and keep media queries for inline-styles blocks
116
   *
117
   * @var bool
118
   */
119
  private $excludeCssCharset = true;
120
121
  /**
122
   * Creates an instance, you could set the HTML and CSS here, or load it
123
   * later.
124
   *
125
   * @param  null|string $html The HTML to process.
126
   * @param  null|string $css  The CSS to use.
127
   */
128 44
  public function __construct($html = null, $css = null)
129
  {
130 44
    if (null !== $html) {
131 1
      $this->setHTML($html);
132 1
    }
133
134 44
    if (null !== $css) {
135 1
      $this->setCSS($css);
136 1
    }
137 44
  }
138
139
  /**
140
   * Set HTML to process
141
   *
142
   * @param  string $html The HTML to process.
143
   */
144 42
  public function setHTML($html)
145
  {
146
    // strip style definitions, if we use css-class "cleanup" on a style-element
147 42
    $this->html = (string)preg_replace('/<style[^>]+class="cleanup"[^>]*>.*<\/style>/Usi', ' ', $html);
148 42
  }
149
150
  /**
151
   * Set CSS to use
152
   *
153
   * @param  string $css The CSS to use.
154
   */
155 40
  public function setCSS($css)
156
  {
157 40
    $this->css = (string)$css;
158 40
  }
159
160
  /**
161
   * Sort an array on the specificity element
162
   *
163
   * @return int
164
   *
165
   * @param Specificity[] $e1 The first element.
166
   * @param Specificity[] $e2 The second element.
167
   */
168 15
  private static function sortOnSpecificity($e1, $e2)
169
  {
170
    // Compare the specificity
171 15
    $value = $e1['specificity']->compareTo($e2['specificity']);
172
173
    // if the specificity is the same, use the order in which the element appeared
174 15
    if (0 === $value) {
175 10
      $value = $e1['order'] - $e2['order'];
176 10
    }
177
178 15
    return $value;
179
  }
180
181
  /**
182
   * Converts the loaded HTML into an HTML-string with inline styles based on the loaded CSS
183
   *
184
   * @return string
185
   *
186
   * @param  bool $outputXHTML                 [optional] Should we output valid XHTML?
187
   * @param  int  $libXMLOptions               [optional] $libXMLOptions Since PHP 5.4.0 and Libxml 2.6.0, you may also
188
   *                                                      use the options parameter to specify additional Libxml
189
   *                                                      parameters. Recommend these options: LIBXML_HTML_NOIMPLIED |
190
   *                                                      LIBXML_HTML_NODEFDTD
191
   * @param $path false|string                 [optional] Set the path to your external css-files.
192
   *
193
   * @throws Exception
194
   */
195 42
  public function convert($outputXHTML = false, $libXMLOptions = 0, $path = false)
196
  {
197
    // redefine
198 42
    $outputXHTML = (bool)$outputXHTML;
199
200
    // validate
201 42
    if (!$this->html) {
202 1
      throw new Exception('No HTML provided.');
203
    }
204
205
    // use local variables
206 41
    $css = $this->css;
207
208
    // create new DOMDocument
209 41
    $document = $this->createDOMDocument($this->html, $libXMLOptions);
210
211
    // check if there is some link css reference
212 41
    if ($this->loadCSSFromHTML) {
213 1
      foreach ($document->getElementsByTagName('link') as $node) {
214 1
        $file = ($path ? $path : __DIR__) . '/' .  $node->getAttribute('href');
215
216 1
        if (file_exists($file)) {
217 1
          $css .= file_get_contents($file);
218
219
          // converting to inline css because we don't need/want to load css files, so remove the link
220 1
          $node->parentNode->removeChild($node);
221 1
        }
222 1
      }
223 1
    }
224
225
    // should we use inline style-block
226 41
    if ($this->useInlineStylesBlock) {
227
228 25
      if (true === $this->excludeConditionalInlineStylesBlock) {
229 21
        $this->html = preg_replace(self::$excludeConditionalInlineStylesBlockRegEx, '', $this->html);
230 21
      }
231
232 25
      $css .= $this->getCssFromInlineHtmlStyleBlock($this->html);
233 25
    }
234
235
    // process css
236 41
    $cssRules = $this->processCSS($css);
237
238
    // create new XPath
239 41
    $xPath = $this->createXPath($document, $cssRules);
240
241
    // strip original style tags if we need to
242 41
    if ($this->stripOriginalStyleTags === true) {
243 13
      $this->stripOriginalStyleTags($xPath);
244 13
    }
245
246
    // cleanup the HTML if we need to
247 41
    if (true === $this->cleanup) {
248 3
      $this->cleanupHTML($xPath);
249 3
    }
250
251
    // should we output XHTML?
252 41
    if (true === $outputXHTML) {
253
      // set formatting
254 5
      $document->formatOutput = true;
255
256
      // get the HTML as XML
257 5
      $html = $document->saveXML(null, LIBXML_NOEMPTYTAG);
258
259
      // remove the XML-header
260 5
      return ltrim(preg_replace('/<\?xml.*\?>/', '', $html));
261
    }
262
263
    // just regular HTML 4.01 as it should be used in newsletters
264 36
    return $document->saveHTML();
265
  }
266
267
  /**
268
   * get css from inline-html style-block
269
   *
270
   * @param string $html
271
   *
272
   * @return string
273
   */
274 27
  public function getCssFromInlineHtmlStyleBlock($html)
275
  {
276
    // init var
277 27
    $css = '';
278 27
    $matches = array();
279
280
    // match the style blocks
281 27
    preg_match_all(self::$styleTagRegEx, $html, $matches);
282
283
    // any style-blocks found?
284 27
    if (!empty($matches[2])) {
285
      // add
286 26
      foreach ($matches[2] as $match) {
287 26
        $css .= trim($match) . "\n";
288 26
      }
289 26
    }
290
291 27
    return $css;
292
  }
293
294
  /**
295
   * Process the loaded CSS
296
   *
297
   * @param $css
298
   *
299
   * @return array
300
   */
301 41
  private function processCSS($css)
302
  {
303
    //reset current set of rules
304 41
    $cssRules = array();
305
306
    // init vars
307 41
    $css = (string)$css;
308
309 41
    $css = $this->doCleanup($css);
310
311
    // rules are splitted by }
312 41
    $rules = (array)explode('}', $css);
313
314
    // init var
315 41
    $i = 1;
316
317
    // loop rules
318 41
    foreach ($rules as $rule) {
319
      // split into chunks
320 41
      $chunks = explode('{', $rule);
321
322
      // invalid rule?
323 41
      if (!isset($chunks[1])) {
324 41
        continue;
325
      }
326
327
      // set the selectors
328 31
      $selectors = trim($chunks[0]);
329
330
      // get cssProperties
331 31
      $cssProperties = trim($chunks[1]);
332
333
      // split multiple selectors
334 31
      $selectors = (array)explode(',', $selectors);
335
336
      // loop selectors
337 31
      foreach ($selectors as $selector) {
338
        // cleanup
339 31
        $selector = trim($selector);
340
341
        // build an array for each selector
342 31
        $ruleSet = array();
343
344
        // store selector
345 31
        $ruleSet['selector'] = $selector;
346
347
        // process the properties
348 31
        $ruleSet['properties'] = $this->processCSSProperties($cssProperties);
349
350
351
        // calculate specificity
352 31
        $ruleSet['specificity'] = Specificity::fromSelector($selector);
353
354
        // remember the order in which the rules appear
355 31
        $ruleSet['order'] = $i;
356
357
        // add into rules
358 31
        $cssRules[] = $ruleSet;
359
360
        // increment
361 31
        $i++;
362 31
      }
363 41
    }
364
365
    // sort based on specificity
366 41
    if (0 !== count($cssRules)) {
367 31
      usort($cssRules, array(__CLASS__, 'sortOnSpecificity'));
368 31
    }
369
370 41
    return $cssRules;
371
  }
372
373
  /**
374
   * @param string $css
375
   *
376
   * @return string
377
   */
378 41
  private function doCleanup($css)
379
  {
380
    // remove newlines & replace double quotes by single quotes
381 41
    $css = str_replace(
382 41
        array("\r", "\n", '"'),
383 41
        array('', '', '\''),
384
        $css
385 41
    );
386
387
    // remove comments
388 41
    $css = preg_replace(self::$styleCommentRegEx, '', $css);
389
390
    // remove spaces
391 41
    $css = preg_replace('/\s\s+/', ' ', $css);
392
393
    // remove css charset
394 41
    if (true === $this->excludeCssCharset) {
395 41
      $css = $this->stripeCharsetInCss($css);
396 41
    }
397
398
    // remove css media queries
399 41
    if (true === $this->excludeMediaQueries) {
400 40
      $css = $this->stripeMediaQueries($css);
401 40
    }
402
403 41
    return (string)$css;
404
  }
405
406
  /**
407
   * remove css media queries from the string
408
   *
409
   * @param string $css
410
   *
411
   * @return string
412
   */
413 40
  private function stripeMediaQueries($css)
414
  {
415
    // remove comments previously to matching media queries
416 40
    $css = preg_replace(self::$styleCommentRegEx, '', $css);
417
418 40
    return (string)preg_replace(self::$cssMediaQueriesRegEx, '', $css);
419
  }
420
421
  /**
422
   * remove charset from the string
423
   *
424
   * @param $css
425
   *
426
   * @return string
427
   */
428 41
  private function stripeCharsetInCss($css)
429
  {
430 41
    return (string)preg_replace(self::$cssCharsetRegEx, '', $css);
431
  }
432
433
  /**
434
   * Process the CSS-properties
435
   *
436
   * @return array
437
   *
438
   * @param  string $propertyString The CSS-properties.
439
   */
440 31
  private function processCSSProperties($propertyString)
441
  {
442
    // split into chunks
443 31
    $properties = $this->splitIntoProperties($propertyString);
444
445
    // init var
446 31
    $pairs = array();
447
448
    // loop properties
449 31
    foreach ($properties as $property) {
450
      // split into chunks
451 31
      $chunks = (array)explode(':', $property, 2);
452
453
      // validate
454 31
      if (!isset($chunks[1])) {
455 25
        continue;
456
      }
457
458
      // cleanup
459 30
      $chunks[0] = trim($chunks[0]);
460 30
      $chunks[1] = trim($chunks[1]);
461
462
      // add to pairs array
463
      if (
464 30
          !isset($pairs[$chunks[0]])
465 30
          ||
466 3
          !in_array($chunks[1], $pairs[$chunks[0]], true)
467 30
      ) {
468 30
        $pairs[$chunks[0]][] = $chunks[1];
469 30
      }
470 31
    }
471
472
    // sort the pairs
473 31
    ksort($pairs);
474
475
    // return
476 31
    return $pairs;
477
  }
478
479
  /**
480
   * Split a style string into an array of properties.
481
   * The returned array can contain empty strings.
482
   *
483
   * @param string $styles ex: 'color:blue;font-size:12px;'
484
   *
485
   * @return array an array of strings containing css property ex: array('color:blue','font-size:12px')
486
   */
487 31
  private function splitIntoProperties($styles)
488
  {
489 31
    $properties = (array)explode(';', $styles);
490 31
    $propertiesCount = count($properties);
491
492 31
    for ($i = 0; $i < $propertiesCount; $i++) {
493
      // If next property begins with base64,
494
      // Then the ';' was part of this property (and we should not have split on it).
495
      if (
496 31
          isset($properties[$i + 1])
497 31
          &&
498 24
          strpos($properties[$i + 1], 'base64,') !== false
499 31
      ) {
500 1
        $properties[$i] .= ';' . $properties[$i + 1];
501 1
        $properties[$i + 1] = '';
502 1
        ++$i;
503 1
      }
504 31
    }
505
506 31
    return $properties;
507
  }
508
509
  /**
510
   * create DOMDocument from HTML
511
   *
512
   * @param string $html
513
   * @param int    $libXMLOptions
514
   *
515
   * @return \DOMDocument
516
   */
517 41
  private function createDOMDocument($html, $libXMLOptions = 0)
518
  {
519
    // create new DOMDocument
520 41
    $document = new \DOMDocument('1.0', $this->getEncoding());
521
522
    // DOMDocument settings
523 41
    $document->preserveWhiteSpace = false;
524 41
    $document->formatOutput = true;
525
526
    // set error level
527 41
    $internalErrors = libxml_use_internal_errors(true);
528
529
    // load HTML
530
    //
531
    // with UTF-8 hack: http://php.net/manual/en/domdocument.loadhtml.php#95251
532
    //
533 41
    if ($libXMLOptions !== 0) {
534
      $document->loadHTML('<?xml encoding="' . $this->getEncoding() . '">' . $html, $libXMLOptions);
535
    } else {
536 41
      $document->loadHTML('<?xml encoding="' . $this->getEncoding() . '">' . $html);
537
    }
538
539
540
    // remove the "xml-encoding" hack
541 41
    foreach ($document->childNodes as $child) {
542 41
      if ($child->nodeType == XML_PI_NODE) {
543 41
        $document->removeChild($child);
544 41
      }
545 41
    }
546
547
    // set encoding
548 41
    $document->encoding = $this->getEncoding();
549
550
    // restore error level
551 41
    libxml_use_internal_errors($internalErrors);
552
553 41
    return $document;
554
  }
555
556
  /**
557
   * Get the encoding to use
558
   *
559
   * @return string
560
   */
561 41
  private function getEncoding()
562
  {
563 41
    return $this->encoding;
564
  }
565
566
  /**
567
   * create XPath
568
   *
569
   * @param \DOMDocument $document
570
   * @param array        $cssRules
571
   *
572
   * @return \DOMXPath
573
   */
574 41
  private function createXPath(\DOMDocument $document, array $cssRules)
575
  {
576 41
    $xPath = new \DOMXPath($document);
577
578
    // any rules?
579 41
    if (0 !== count($cssRules)) {
580
      // loop rules
581 31
      foreach ($cssRules as $rule) {
582
583
        try {
584 31
          $converter = new CssSelectorConverter();
585 31
          $query = $converter->toXPath($rule['selector']);
586 31
        } catch (ExceptionInterface $e) {
587 4
          $query = null;
588
        }
589 31
        $converter = null;
590
591
        // validate query
592 31
        if (null === $query) {
593 4
          continue;
594
        }
595
596
        // search elements
597 29
        $elements = $xPath->query($query);
598
599
        // validate elements
600 29
        if (false === $elements) {
601
          continue;
602
        }
603
604
        // loop found elements
605 29
        foreach ($elements as $element) {
606
607
          /**
608
           * @var $element \DOMElement
609
           */
610
611
          // no styles stored?
612 29
          if (null === $element->attributes->getNamedItem('data-css-to-inline-styles-original-styles')) {
613
614
            // init var
615 29
            $originalStyle = '';
616
617 29
            if (null !== $element->attributes->getNamedItem('style')) {
618 6
              $originalStyle = $element->attributes->getNamedItem('style')->value;
619 6
            }
620
621
            // store original styles
622 29
            $element->setAttribute('data-css-to-inline-styles-original-styles', $originalStyle);
623
624
            // clear the styles
625 29
            $element->setAttribute('style', '');
626 29
          }
627
628 29
          $propertiesString = $this->createPropertyChunks($element, $rule['properties']);
629
630
          // set attribute
631 29
          if ('' != $propertiesString) {
632 29
            $element->setAttribute('style', $propertiesString);
633 29
          }
634 29
        }
635 31
      }
636
637
      // reapply original styles
638
      // search elements
639 31
      $elements = $xPath->query('//*[@data-css-to-inline-styles-original-styles]');
640
641
      // loop found elements
642 31
      foreach ($elements as $element) {
643
        // get the original styles
644 29
        $originalStyle = $element->attributes->getNamedItem('data-css-to-inline-styles-original-styles')->value;
645
646 29
        if ('' != $originalStyle) {
647 6
          $originalStyles = $this->splitIntoProperties($originalStyle);
648
649 6
          $originalProperties = $this->splitStyleIntoChunks($originalStyles);
650
651 6
          $propertiesString = $this->createPropertyChunks($element, $originalProperties);
652
653
          // set attribute
654 6
          if ('' != $propertiesString) {
655 6
            $element->setAttribute('style', $propertiesString);
656 6
          }
657 6
        }
658
659
        // remove placeholder
660 29
        $element->removeAttribute('data-css-to-inline-styles-original-styles');
661 31
      }
662 31
    }
663
664 41
    return $xPath;
665
  }
666
667
  /**
668
   * @param \DOMElement $element
669
   * @param array       $ruleProperties
670
   *
671
   * @return array
672
   */
673 29
  private function createPropertyChunks(\DOMElement $element, array $ruleProperties)
674
  {
675
    // init var
676 29
    $properties = array();
677
678
    // get current styles
679 29
    $stylesAttribute = $element->attributes->getNamedItem('style');
680
681
    // any styles defined before?
682 29
    if (null !== $stylesAttribute) {
683
      // get value for the styles attribute
684 29
      $definedStyles = (string)$stylesAttribute->value;
685
686
      // split into properties
687 29
      $definedProperties = $this->splitIntoProperties($definedStyles);
688
689 29
      $properties = $this->splitStyleIntoChunks($definedProperties);
690 29
    }
691
692
    // add new properties into the list
693 29
    foreach ($ruleProperties as $key => $value) {
694
      // If one of the rules is already set and is !important, don't apply it,
695
      // except if the new rule is also important.
696
      if (
697 29
          !isset($properties[$key])
698 29
          ||
699 7
          false === stripos($properties[$key], '!important')
700 7
          ||
701 3
          false !== stripos(implode('', (array)$value), '!important')
702 29
      ) {
703 29
        $properties[$key] = $value;
704 29
      }
705 29
    }
706
707
    // build string
708 29
    $propertyChunks = array();
709
710
    // build chunks
711 29
    foreach ($properties as $key => $values) {
712 29
      foreach ((array)$values as $value) {
713 29
        $propertyChunks[] = $key . ': ' . $value . ';';
714 29
      }
715 29
    }
716
717 29
    return implode(' ', $propertyChunks);
718
  }
719
720
  /**
721
   * @param array $definedProperties
722
   *
723
   * @return array
724
   */
725 29
  private function splitStyleIntoChunks(array $definedProperties)
726
  {
727
    // init var
728 29
    $properties = array();
729
730
    // loop properties
731 29
    foreach ($definedProperties as $property) {
732
      // validate property
733
      if (
734
          !$property
735 29
          ||
736 14
          strpos($property, ':') === false
737 29
      ) {
738 29
        continue;
739
      }
740
741
      // split into chunks
742 14
      $chunks = (array)explode(':', trim($property), 2);
743
744
      // validate
745 14
      if (!isset($chunks[1])) {
746
        continue;
747
      }
748
749
      // loop chunks
750 14
      $properties[$chunks[0]] = trim($chunks[1]);
751 29
    }
752
753 29
    return $properties;
754
  }
755
756
  /**
757
   * Strip style tags into the generated HTML
758
   *
759
   * @param  \DOMXPath $xPath The DOMXPath for the entire document.
760
   *
761
   * @return string
762
   */
763 13
  private function stripOriginalStyleTags(\DOMXPath $xPath)
764
  {
765
    // get all style tags
766 13
    $nodes = $xPath->query('descendant-or-self::style');
767 13
    foreach ($nodes as $node) {
768 12
      if ($this->excludeMediaQueries === true) {
769
770
        // remove comments previously to matching media queries
771 11
        $node->nodeValue = preg_replace(self::$styleCommentRegEx, '', $node->nodeValue);
772
773
        // search for Media Queries
774 11
        preg_match_all(self::$cssMediaQueriesRegEx, $node->nodeValue, $mqs);
775
776
        // replace the nodeValue with just the Media Queries
777 11
        $node->nodeValue = implode("\n", $mqs[0]);
778
779 11
      } else {
780
        // remove the entire style tag
781 1
        $node->parentNode->removeChild($node);
782
      }
783 13
    }
784 13
  }
785
786
  /**
787
   * Remove id and class attributes.
788
   *
789
   * @param  \DOMXPath $xPath The DOMXPath for the entire document.
790
   *
791
   * @return string
792
   */
793 3
  private function cleanupHTML(\DOMXPath $xPath)
794
  {
795 3
    $nodes = $xPath->query('//@class | //@id');
796 3
    foreach ($nodes as $node) {
797 3
      $node->ownerElement->removeAttributeNode($node);
798 3
    }
799 3
  }
800
801
  /**
802
   * Should the IDs and classes be removed?
803
   *
804
   * @param  bool $on Should we enable cleanup?
805
   */
806 3
  public function setCleanup($on = true)
807
  {
808 3
    $this->cleanup = (bool)$on;
809 3
  }
810
811
  /**
812
   * Set the encoding to use with the DOMDocument
813
   *
814
   * @param  string $encoding The encoding to use.
815
   *
816
   * @deprecated Doesn't have any effect
817
   */
818
  public function setEncoding($encoding)
819
  {
820
    $this->encoding = (string)$encoding;
821
  }
822
823
  /**
824
   * Set use of inline styles block
825
   * If this is enabled the class will use the style-block in the HTML.
826
   *
827
   * @param  bool $on Should we process inline styles?
828
   */
829 25
  public function setUseInlineStylesBlock($on = true)
830
  {
831 25
    $this->useInlineStylesBlock = (bool)$on;
832 25
  }
833
834
  /**
835
       * Set use of inline link block
836
       * If this is enabled the class will use the links reference in the HTML.
837
       *
838
       * @return void
839
       * @param  bool [optional] $on Should we process link styles?
840
       */
841 1
    public function setLoadCSSFromHTML($on = true)
842
     {
843 1
         $this->loadCSSFromHTML = (bool) $on;
844 1
     }
845
846
  /**
847
   * Set strip original style tags
848
   * If this is enabled the class will remove all style tags in the HTML.
849
   *
850
   * @param  bool $on Should we process inline styles?
851
   */
852 16
  public function setStripOriginalStyleTags($on = true)
853
  {
854 16
    $this->stripOriginalStyleTags = (bool)$on;
855 16
  }
856
857
  /**
858
   * Set exclude media queries
859
   *
860
   * If this is enabled the media queries will be removed before inlining the rules.
861
   *
862
   * WARNING: If you use inline styles block "<style>" the this option will keep the media queries.
863
   *
864
   * @param bool $on
865
   */
866 13
  public function setExcludeMediaQueries($on = true)
867
  {
868 13
    $this->excludeMediaQueries = (bool)$on;
869 13
  }
870
871
  /**
872
   * Set exclude charset
873
   *
874
   * @param bool $on
875
   */
876 1
  public function setExcludeCssCharset($on = true)
877
  {
878 1
    $this->excludeCssCharset = (bool)$on;
879 1
  }
880
881
  /**
882
   * Set exclude conditional inline-style blocks e.g.: <!--[if gte mso 9]><style>.foo { bar } </style><![endif]-->
883
   *
884
   * @param bool $on
885
   */
886 5
  public function setExcludeConditionalInlineStylesBlock($on = true)
887
  {
888 5
    $this->excludeConditionalInlineStylesBlock = (bool)$on;
889 5
  }
890
891
}
892