Completed
Push — master ( 9dc866...06f54c )
by Lars
06:38
created

CssToInlineStyles::setExcludeCssCharset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
namespace voku\CssToInlineStyles;
4
5
use Symfony\Component\CssSelector\CssSelectorConverter;
6
use Symfony\Component\CssSelector\Exception\ExceptionInterface;
7
use voku\helper\HtmlDomParser;
8
9
/**
10
 * CSS to Inline Styles class
11
 *
12
 * @author     Tijs Verkoyen <[email protected]>
13
 */
14
class CssToInlineStyles
15
{
16
17
  /**
18
   * @var CssSelectorConverter
19
   */
20
  private $cssConverter;
21
22
  /**
23
   * regular expression: css media queries
24
   *
25
   * @var string
26
   */
27
  private static $cssMediaQueriesRegEx = '#@media\\s+(?:only\\s)?(?:[\\s{\\(]|screen|all)\\s?[^{]+{.*}\\s*}\\s*#misU';
28
29
  /**
30
   * regular expression: css charset
31
   *
32
   * @var string
33
   */
34
  private static $cssCharsetRegEx = '/@charset [\'"][^\'"]+[\'"];/i';
35
36
  /**
37
   * regular expression: conditional inline style tags
38
   *
39
   * @var string
40
   */
41
  private static $excludeConditionalInlineStylesBlockRegEx = '/<!--.*<style.*-->/isU';
42
43
  /**
44
   * regular expression: inline style tags
45
   *
46
   * @var string
47
   */
48
  private static $styleTagRegEx = '|<style(?:\s.*)?>(.*)</style>|isU';
49
50
  /**
51
   * regular expression: style-tag with 'cleanup'-css-class
52
   *
53
   * @var string
54
   */
55
  private static $styleTagWithCleanupClassRegEx = '|<style[^>]+class="cleanup"[^>]*>.*</style>|isU';
56
57
  /**
58
   * regular expression: css-comments
59
   *
60
   * @var string
61
   */
62
  private static $styleCommentRegEx = '/\\/\\*.*\\*\\//sU';
63
64
  /**
65
   * The CSS to use
66
   *
67
   * @var  string
68
   */
69
  private $css;
70
71
  /**
72
   * Should the generated HTML be cleaned
73
   *
74
   * @var  bool
75
   */
76
  private $cleanup = false;
77
78
  /**
79
   * The encoding to use.
80
   *
81
   * @var  string
82
   */
83
  private $encoding = 'UTF-8';
84
85
  /**
86
   * The HTML to process
87
   *
88
   * @var  string
89
   */
90
  private $html;
91
92
  /**
93
   * Use inline-styles block as CSS
94
   *
95
   * @var bool
96
   */
97
  private $useInlineStylesBlock = false;
98
99
  /**
100
   * Use link block reference as CSS
101
   *
102
   * @var bool
103
   */
104
  private $loadCSSFromHTML = false;
105
106
  /**
107
   * Strip original style tags
108
   *
109
   * @var bool
110
   */
111
  private $stripOriginalStyleTags = false;
112
113
  /**
114
   * Exclude conditional inline-style blocks
115
   *
116
   * @var bool
117
   */
118
  private $excludeConditionalInlineStylesBlock = true;
119
120
  /**
121
   * Exclude media queries from "$this->css" and keep media queries for inline-styles blocks
122
   *
123
   * @var bool
124
   */
125
  private $excludeMediaQueries = true;
126
127
  /**
128
   * Exclude media queries from "$this->css" and keep media queries for inline-styles blocks
129
   *
130
   * @var bool
131
   */
132
  private $excludeCssCharset = true;
133
134
  /**
135
   * Creates an instance, you could set the HTML and CSS here, or load it
136
   * later.
137
   *
138
   * @param  null|string $html The HTML to process.
139
   * @param  null|string $css  The CSS to use.
140
   */
141 54
  public function __construct($html = null, $css = null)
142
  {
143 54
    if (null !== $html) {
144 2
      $this->setHTML($html);
145
    }
146
147 54
    if (null !== $css) {
148 2
      $this->setCSS($css);
149
    }
150
151 54
    if (class_exists('Symfony\Component\CssSelector\CssSelectorConverter')) {
152 54
      $this->cssConverter = new CssSelectorConverter();
153
    }
154 54
  }
155
156
  /**
157
   * Set HTML to process
158
   *
159
   * @param  string $html The HTML to process.
160
   *
161
   * @return $this
162
   */
163 52
  public function setHTML($html)
164
  {
165
    // strip style definitions, if we use css-class "cleanup" on a style-element
166 52
    $this->html = (string)preg_replace(self::$styleTagWithCleanupClassRegEx, ' ', $html);
167
168 52
    return $this;
169
  }
170
171
  /**
172
   * Set CSS to use
173
   *
174
   * @param  string $css The CSS to use.
175
   *
176
   * @return $this
177
   */
178 48
  public function setCSS($css)
179
  {
180 48
    $this->css = (string)$css;
181
182 48
    return $this;
183
  }
184
185
  /**
186
   * Sort an array on the specificity element.
187
   *
188
   * @param Specificity[] $e1 The first element.
189
   * @param Specificity[] $e2 The second element.
190
   *
191
   * @return int
192
   */
193 21
  private static function sortOnSpecificity($e1, $e2)
194
  {
195
    // Compare the specificity
196 21
    $value = $e1['specificity']->compareTo($e2['specificity']);
197
198
    // if the specificity is the same, use the order in which the element appeared
199 21
    if (0 === $value) {
200 16
      $value = $e1['order'] - $e2['order'];
201
    }
202
203 21
    return $value;
204
  }
205
206
  /**
207
   * Converts the loaded HTML into an HTML-string with inline styles based on the loaded CSS.
208
   *
209
   * @param bool $outputXHTML            [optional] Should we output valid XHTML?
210
   * @param int|null $libXMLExtraOptions [optional] $libXMLExtraOptions Since PHP 5.4.0 and Libxml 2.6.0,
211
   *                                     you may also use the options parameter to specify additional
212
   *                                     Libxml parameters.
213
   * @param bool $path                   [optional] Set the path to your external css-files.
214
   *
215
   * @return string
216
   *
217
   * @throws Exception
218
   */
219 52
  public function convert($outputXHTML = false, $libXMLExtraOptions = null, $path = false)
220
  {
221
    // init
222 52
    $outputXHTML = (bool)$outputXHTML;
223
224
    // validate
225 52
    if (!$this->html) {
226 1
      throw new Exception('No HTML provided.');
227
    }
228
229
    // use local variables
230 51
    $css = $this->css;
231
232
    // create new HtmlDomParser
233 51
    $dom = HtmlDomParser::str_get_html($this->html, $libXMLExtraOptions);
0 ignored issues
show
Unused Code introduced by
The call to HtmlDomParser::str_get_html() has too many arguments starting with $this->html.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
234
235
    // check if there is some link css reference
236 51
    if ($this->loadCSSFromHTML) {
237 1
      foreach ($dom->find('link') as $node) {
238
239 1
        $file = ($path ?: __DIR__) . '/' . $node->getAttribute('href');
240
241 1
        if (file_exists($file)) {
242 1
          $css .= file_get_contents($file);
243
244
          // converting to inline css because we don't need/want to load css files, so remove the link
245 1
          $node->outertext = '';
246
        }
247
      }
248
    }
249
250
    // should we use inline style-block
251 51
    if ($this->useInlineStylesBlock) {
252
253 29
      if (true === $this->excludeConditionalInlineStylesBlock) {
254 25
        $this->html = preg_replace(self::$excludeConditionalInlineStylesBlockRegEx, '', $this->html);
255
      }
256
257 29
      $css .= $this->getCssFromInlineHtmlStyleBlock($this->html);
258
    }
259
260
    // process css
261 51
    $cssRules = $this->processCSS($css);
262
263
    // create new XPath
264 51
    $xPath = $this->createXPath($dom->getDocument(), $cssRules);
265
266
    // strip original style tags if we need to
267 51
    if ($this->stripOriginalStyleTags === true) {
268 13
      $this->stripOriginalStyleTags($xPath);
269
    }
270
271
    // cleanup the HTML if we need to
272 51
    if (true === $this->cleanup) {
273 3
      $this->cleanupHTML($xPath);
274
    }
275
276
    // should we output XHTML?
277 51
    if (true === $outputXHTML) {
278 6
      return $dom->xml();
279
    }
280
281
    // just regular HTML 4.01 as it should be used in newsletters
282 46
    return $dom->html();
283
  }
284
285
  /**
286
   * get css from inline-html style-block
287
   *
288
   * @param string $html
289
   *
290
   * @return string
291
   */
292 31
  public function getCssFromInlineHtmlStyleBlock($html)
293
  {
294
    // init var
295 31
    $css = '';
296 31
    $matches = array();
297
298
    // match the style blocks
299 31
    preg_match_all(self::$styleTagRegEx, $html, $matches);
300
301
    // any style-blocks found?
302 31
    if (!empty($matches[1])) {
303
      // add
304 30
      foreach ($matches[1] as $match) {
305 30
        $css .= trim($match) . "\n";
306
      }
307
    }
308
309 31
    return $css;
310
  }
311
312
  /**
313
   * Process the loaded CSS
314
   *
315
   * @param string $css
316
   *
317
   * @return array
318
   */
319 51
  private function processCSS($css)
320
  {
321
    //reset current set of rules
322 51
    $cssRules = array();
323
324
    // init vars
325 51
    $css = (string)$css;
326
327 51
    $css = $this->doCleanup($css);
328
329
    // rules are splitted by }
330 51
    $rules = (array)explode('}', $css);
331
332
    // init var
333 51
    $i = 1;
334
335
    // loop rules
336 51
    foreach ($rules as $rule) {
337
      // split into chunks
338 51
      $chunks = explode('{', $rule);
339
340
      // invalid rule?
341 51
      if (!isset($chunks[1])) {
342 51
        continue;
343
      }
344
345
      // set the selectors
346 38
      $selectors = trim($chunks[0]);
347
348
      // get cssProperties
349 38
      $cssProperties = trim($chunks[1]);
350
351
      // split multiple selectors
352 38
      $selectors = (array)explode(',', $selectors);
353
354
      // loop selectors
355 38
      foreach ($selectors as $selector) {
356
        // cleanup
357 38
        $selector = trim($selector);
358
359
        // build an array for each selector
360 38
        $ruleSet = array();
361
362
        // store selector
363 38
        $ruleSet['selector'] = $selector;
364
365
        // process the properties
366 38
        $ruleSet['properties'] = $this->processCSSProperties($cssProperties);
367
368
        // calculate specificity
369 38
        $ruleSet['specificity'] = Specificity::fromSelector($selector);
370
371
        // remember the order in which the rules appear
372 38
        $ruleSet['order'] = $i;
373
374
        // add into rules
375 38
        $cssRules[] = $ruleSet;
376
377
        // increment
378 38
        $i++;
379
      }
380
    }
381
382
    // sort based on specificity
383 51
    if (0 !== count($cssRules)) {
384 38
      usort($cssRules, array(__CLASS__, 'sortOnSpecificity'));
385
    }
386
387 51
    return $cssRules;
388
  }
389
390
  /**
391
   * @param string $css
392
   *
393
   * @return string
394
   */
395 51
  private function doCleanup($css)
396
  {
397
    // remove newlines & replace double quotes by single quotes
398 51
    $css = str_replace(
399 51
        array("\r", "\n", '"'),
400 51
        array('', '', '\''),
401
        $css
402
    );
403
404
    // remove comments
405 51
    $css = preg_replace(self::$styleCommentRegEx, '', $css);
406
407
    // remove spaces
408 51
    $css = preg_replace('/\s\s+/', ' ', $css);
409
410
    // remove css charset
411 51
    if (true === $this->excludeCssCharset) {
412 51
      $css = $this->stripeCharsetInCss($css);
413
    }
414
415
    // remove css media queries
416 51
    if (true === $this->excludeMediaQueries) {
417 50
      $css = $this->stripeMediaQueries($css);
418
    }
419
420 51
    return (string)$css;
421
  }
422
423
  /**
424
   * remove css media queries from the string
425
   *
426
   * @param string $css
427
   *
428
   * @return string
429
   */
430 50
  private function stripeMediaQueries($css)
431
  {
432
    // remove comments previously to matching media queries
433 50
    $css = preg_replace(self::$styleCommentRegEx, '', $css);
434
435 50
    return (string)preg_replace(self::$cssMediaQueriesRegEx, '', $css);
436
  }
437
438
  /**
439
   * remove charset from the string
440
   *
441
   * @param string $css
442
   *
443
   * @return string
444
   */
445 51
  private function stripeCharsetInCss($css)
446
  {
447 51
    return (string)preg_replace(self::$cssCharsetRegEx, '', $css);
448
  }
449
450
  /**
451
   * Process the CSS-properties
452
   *
453
   * @return array
454
   *
455
   * @param  string $propertyString The CSS-properties.
456
   */
457 38
  private function processCSSProperties($propertyString)
458
  {
459
    // split into chunks
460 38
    $properties = $this->splitIntoProperties($propertyString);
461
462
    // init var
463 38
    $pairs = array();
464
465
    // loop properties
466 38
    foreach ($properties as $property) {
467
      // split into chunks
468 38
      $chunks = (array)explode(':', $property, 2);
469
470
      // validate
471 38
      if (!isset($chunks[1])) {
472 32
        continue;
473
      }
474
475
      // cleanup
476 37
      $chunks[0] = trim($chunks[0]);
477 37
      $chunks[1] = trim($chunks[1]);
478
479
      // add to pairs array
480
      if (
481 37
          !isset($pairs[$chunks[0]])
482
          ||
483 37
          !in_array($chunks[1], $pairs[$chunks[0]], true)
484
      ) {
485 37
        $pairs[$chunks[0]][] = $chunks[1];
486
      }
487
    }
488
489
    // sort the pairs
490 38
    ksort($pairs);
491
492
    // return
493 38
    return $pairs;
494
  }
495
496
  /**
497
   * Split a style string into an array of properties.
498
   * The returned array can contain empty strings.
499
   *
500
   * @param string $styles ex: 'color:blue;font-size:12px;'
501
   *
502
   * @return array an array of strings containing css property ex: array('color:blue','font-size:12px')
503
   */
504 38
  private function splitIntoProperties($styles)
505
  {
506 38
    $properties = (array)explode(';', $styles);
507 38
    $propertiesCount = count($properties);
508
509
    /** @noinspection ForeachInvariantsInspection */
510 38
    for ($i = 0; $i < $propertiesCount; $i++) {
511
      // If next property begins with base64,
512
      // Then the ';' was part of this property (and we should not have split on it).
513
      if (
514 38
          isset($properties[$i + 1])
515
          &&
516 38
          strpos($properties[$i + 1], 'base64,') !== false
517
      ) {
518 1
        $properties[$i] .= ';' . $properties[$i + 1];
519 1
        $properties[$i + 1] = '';
520 1
        ++$i;
521
      }
522
    }
523
524 38
    return $properties;
525
  }
526
527
  /**
528
   * create XPath
529
   *
530
   * @param \DOMDocument $document
531
   * @param array        $cssRules
532
   *
533
   * @return \DOMXPath
534
   */
535 51
  private function createXPath(\DOMDocument $document, array $cssRules)
536
  {
537 51
    $propertyStorage = new \SplObjectStorage();
538 51
    $xPath = new \DOMXPath($document);
539
540
    // any rules?
541 51
    if (0 !== count($cssRules)) {
542
      // loop rules
543 38
      foreach ($cssRules as $rule) {
544
545 38
        $ruleSelector = $rule['selector'];
546 38
        $ruleProperties = $rule['properties'];
547
548 38
        if (!$ruleSelector || !$ruleProperties) {
549 3
          continue;
550
        }
551
552
        try {
553 37
          $query = $this->cssConverter->toXPath($ruleSelector);
554 4
        } catch (ExceptionInterface $e) {
555 4
          $query = null;
556
        }
557
558
        // validate query
559 37
        if (null === $query) {
560 4
          continue;
561
        }
562
563
        // search elements
564 36
        $elements = $xPath->query($query);
565
566
        // validate elements
567 36
        if (false === $elements) {
568
          continue;
569
        }
570
571
        // loop found elements
572 36
        foreach ($elements as $element) {
573
574
          /**
575
           * @var $element \DOMElement
576
           */
577
578
          if (
579 36
              $ruleSelector == '*'
580
              &&
581
              (
582 1
                  $element->tagName == 'html'
583 1
                  || $element->tagName === 'title'
584 1
                  || $element->tagName == 'meta'
585 1
                  || $element->tagName == 'head'
586 1
                  || $element->tagName == 'style'
587 1
                  || $element->tagName == 'script'
588 36
                  || $element->tagName == 'link'
589
              )
590
          ) {
591 1
            continue;
592
          }
593
594
          // no styles stored?
595 36
          if (!isset($propertyStorage[$element])) {
596
597
            // init var
598 36
            $originalStyle = $element->attributes->getNamedItem('style');
599
600 36
            if ($originalStyle) {
601 10
              $originalStyle = $originalStyle->value;
0 ignored issues
show
Bug introduced by
The property value does not seem to exist in DOMNode.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
602
            } else {
603 34
              $originalStyle = '';
604
            }
605
606
            // store original styles
607 36
            $propertyStorage->attach($element, $originalStyle);
608
609
            // clear the styles
610 36
            $element->setAttribute('style', '');
611
          }
612
613
          // set attribute
614 36
          $propertiesString = $this->createPropertyChunks($element, $ruleProperties);
615 36
          if ($propertiesString) {
616 36
            $element->setAttribute('style', $propertiesString);
617
          }
618
        }
619
      }
620
621 38
      foreach ($propertyStorage as $element) {
622 36
        $originalStyle = $propertyStorage->getInfo();
623 36
        if ($originalStyle) {
624 10
          $originalStyles = $this->splitIntoProperties($originalStyle);
625 10
          $originalProperties = $this->splitStyleIntoChunks($originalStyles);
626
627
          // set attribute
628 10
          $propertiesString = $this->createPropertyChunks($element, $originalProperties);
629 10
          if ($propertiesString) {
630 36
            $element->setAttribute('style', $propertiesString);
631
          }
632
        }
633
      }
634
    }
635
636 51
    return $xPath;
637
  }
638
639
  /**
640
   * @param \DOMElement $element
641
   * @param array       $ruleProperties
642
   *
643
   * @return string
644
   */
645 36
  private function createPropertyChunks(\DOMElement $element, array $ruleProperties)
646
  {
647
    // init var
648 36
    $properties = array();
649
650
    // get current styles
651 36
    $stylesAttribute = $element->attributes->getNamedItem('style');
652
653
    // any styles defined before?
654 36
    if (null !== $stylesAttribute) {
655
      // get value for the styles attribute
656 36
      $definedStyles = (string)$stylesAttribute->value;
0 ignored issues
show
Bug introduced by
The property value does not seem to exist in DOMNode.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
657
658
      // split into properties
659 36
      $definedProperties = $this->splitIntoProperties($definedStyles);
660
661 36
      $properties = $this->splitStyleIntoChunks($definedProperties);
662
    }
663
664
    // add new properties into the list
665 36
    foreach ($ruleProperties as $key => $value) {
666
      // If one of the rules is already set and is !important, don't apply it,
667
      // except if the new rule is also important.
668
      if (
669 36
          !isset($properties[$key])
670
          ||
671 11
          false === stripos($properties[$key], '!important')
672
          ||
673 36
          false !== stripos(implode('', (array)$value), '!important')
674
      ) {
675 36
        unset($properties[$key]);
676 36
        $properties[$key] = $value;
677
      }
678
    }
679
680
    // build string
681 36
    $propertyChunks = array();
682
683
    // build chunks
684 36
    foreach ($properties as $key => $values) {
685 36
      foreach ((array)$values as $value) {
686 36
        $propertyChunks[] = $key . ': ' . $value . ';';
687
      }
688
    }
689
690 36
    return implode(' ', $propertyChunks);
691
  }
692
693
  /**
694
   * @param array $definedProperties
695
   *
696
   * @return array
697
   */
698 36
  private function splitStyleIntoChunks(array $definedProperties)
699
  {
700
    // init var
701 36
    $properties = array();
702
703
    // loop properties
704 36
    foreach ($definedProperties as $property) {
705
      // validate property
706
      if (
707 36
          !$property
708
          ||
709 36
          strpos($property, ':') === false
710
      ) {
711 36
        continue;
712
      }
713
714
      // split into chunks
715 18
      $chunks = (array)explode(':', trim($property), 2);
716
717
      // validate
718 18
      if (!isset($chunks[1])) {
719
        continue;
720
      }
721
722
      // loop chunks
723 18
      $properties[$chunks[0]] = trim($chunks[1]);
724
    }
725
726 36
    return $properties;
727
  }
728
729
  /**
730
   * Strip style tags into the generated HTML.
731
   *
732
   * @param  \DOMXPath $xPath The DOMXPath for the entire document.
733
   */
734 13
  private function stripOriginalStyleTags(\DOMXPath $xPath)
735
  {
736
    // get all style tags
737 13
    $nodes = $xPath->query('descendant-or-self::style');
738 13
    foreach ($nodes as $node) {
739 12
      if ($this->excludeMediaQueries === true) {
740
741
        // remove comments previously to matching media queries
742 11
        $node->nodeValue = preg_replace(self::$styleCommentRegEx, '', $node->nodeValue);
743
744
        // search for Media Queries
745 11
        preg_match_all(self::$cssMediaQueriesRegEx, $node->nodeValue, $mqs);
746
747
        // replace the nodeValue with just the Media Queries
748 11
        $node->nodeValue = implode("\n", $mqs[0]);
749
750
      } else {
751
        // remove the entire style tag
752 12
        $node->parentNode->removeChild($node);
753
      }
754
    }
755 13
  }
756
757
  /**
758
   * Remove id and class attributes.
759
   *
760
   * @param  \DOMXPath $xPath The DOMXPath for the entire document.
761
   */
762 3
  private function cleanupHTML(\DOMXPath $xPath)
763
  {
764 3
    $nodes = $xPath->query('//@class | //@id');
765 3
    foreach ($nodes as $node) {
766 3
      $node->ownerElement->removeAttributeNode($node);
767
    }
768 3
  }
769
770
  /**
771
   * Should the IDs and classes be removed?
772
   *
773
   * @param  bool $on Should we enable cleanup?
774
   *
775
   * @return $this
776
   */
777 3
  public function setCleanup($on = true)
778
  {
779 3
    $this->cleanup = (bool)$on;
780
781 3
    return $this;
782
  }
783
784
  /**
785
   * Set the encoding to use with the DOMDocument.
786
   *
787
   * @param  string $encoding The encoding to use.
788
   *
789
   * @return $this
790
   *
791
   * @deprecated Doesn't have any effect
792
   */
793
  public function setEncoding($encoding)
794
  {
795
    $this->encoding = (string)$encoding;
796
797
    return $this;
798
  }
799
800
  /**
801
   * Set use of inline styles block.
802
   *
803
   * Info: If this is enabled the class will use the style-block in the HTML.
804
   *
805
   * @param  bool $on Should we process inline styles?
806
   *
807
   * @return $this
808
   */
809 29
  public function setUseInlineStylesBlock($on = true)
810
  {
811 29
    $this->useInlineStylesBlock = (bool)$on;
812
813 29
    return $this;
814
  }
815
816
  /**
817
   * Set use of inline link block.
818
   *
819
   * Info: If this is enabled the class will use the links reference in the HTML.
820
   *
821
   * @param  bool [optional] $on Should we process link styles?
822
   *
823
   * @return $this
824
   */
825 2
  public function setLoadCSSFromHTML($on = true)
826
  {
827 2
    $this->loadCSSFromHTML = (bool)$on;
828
829 2
    return $this;
830
  }
831
832
  /**
833
   * Set strip original style tags.
834
   *
835
   * Info: If this is enabled the class will remove all style tags in the HTML.
836
   *
837
   * @param  bool $on Should we process inline styles?
838
   *
839
   * @return $this
840
   */
841 17
  public function setStripOriginalStyleTags($on = true)
842
  {
843 17
    $this->stripOriginalStyleTags = (bool)$on;
844
845 17
    return $this;
846
  }
847
848
  /**
849
   * Set exclude media queries.
850
   *
851
   * Info: If this is enabled the media queries will be removed before inlining the rules.
852
   *
853
   * WARNING: If you use inline styles block "<style>" the this option will keep the media queries.
854
   *
855
   * @param bool $on
856
   *
857
   * @return $this
858
   */
859 14
  public function setExcludeMediaQueries($on = true)
860
  {
861 14
    $this->excludeMediaQueries = (bool)$on;
862
863 14
    return $this;
864
  }
865
866
  /**
867
   * Set exclude charset.
868
   *
869
   * @param bool $on
870
   *
871
   * @return $this
872
   */
873 1
  public function setExcludeCssCharset($on = true)
874
  {
875 1
    $this->excludeCssCharset = (bool)$on;
876
877 1
    return $this;
878
  }
879
880
  /**
881
   * Set exclude conditional inline-style blocks.
882
   *
883
   * e.g.: <!--[if gte mso 9]><style>.foo { bar } </style><![endif]-->
884
   *
885
   * @param bool $on
886
   *
887
   * @return $this
888
   */
889 6
  public function setExcludeConditionalInlineStylesBlock($on = true)
890
  {
891 6
    $this->excludeConditionalInlineStylesBlock = (bool)$on;
892
893 6
    return $this;
894
  }
895
}
896