Completed
Push — master ( 06f54c...228241 )
by Lars
07:56
created

getCssFromInlineHtmlStyleBlock()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 5
Bugs 2 Features 0
Metric Value
c 5
b 2
f 0
dl 0
loc 19
ccs 10
cts 10
cp 1
rs 9.4285
cc 3
eloc 8
nc 2
nop 1
crap 3
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 55
  public function __construct($html = null, $css = null)
142
  {
143 55
    if (null !== $html) {
144 2
      $this->setHTML($html);
145 2
    }
146
147 55
    if (null !== $css) {
148 2
      $this->setCSS($css);
149 2
    }
150
151 55
    if (class_exists('Symfony\Component\CssSelector\CssSelectorConverter')) {
152 55
      $this->cssConverter = new CssSelectorConverter();
153 55
    }
154 55
  }
155
156
  /**
157
   * Set HTML to process
158
   *
159
   * @param  string $html The HTML to process.
160
   *
161
   * @return $this
162
   */
163 53
  public function setHTML($html)
164
  {
165
    // strip style definitions, if we use css-class "cleanup" on a style-element
166 53
    $this->html = (string)preg_replace(self::$styleTagWithCleanupClassRegEx, ' ', $html);
167
168 53
    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 22
  private static function sortOnSpecificity($e1, $e2)
194
  {
195
    // Compare the specificity
196 22
    $value = $e1['specificity']->compareTo($e2['specificity']);
197
198
    // if the specificity is the same, use the order in which the element appeared
199 22
    if (0 === $value) {
200 17
      $value = $e1['order'] - $e2['order'];
201 17
    }
202
203 22
    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 53
  public function convert($outputXHTML = false, $libXMLExtraOptions = null, $path = false)
220
  {
221
    // init
222 53
    $outputXHTML = (bool)$outputXHTML;
223
224
    // validate
225 53
    if (!$this->html) {
226 1
      throw new Exception('No HTML provided.');
227
    }
228
229
    // use local variables
230 52
    $css = $this->css;
231
232
    // create new HtmlDomParser
233 52
    $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 52
    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 1
        }
247 1
      }
248 1
    }
249
250
    // should we use inline style-block
251 52
    if ($this->useInlineStylesBlock) {
252
253 30
      if (true === $this->excludeConditionalInlineStylesBlock) {
254 26
        $this->html = preg_replace(self::$excludeConditionalInlineStylesBlockRegEx, '', $this->html);
255 26
      }
256
257 30
      $css .= $this->getCssFromInlineHtmlStyleBlock($this->html);
258 30
    }
259
260
    // process css
261 52
    $cssRules = $this->processCSS($css);
262
263
    // create new XPath
264 52
    $xPath = $this->createXPath($dom->getDocument(), $cssRules);
265
266
    // strip original style tags if we need to
267 52
    if ($this->stripOriginalStyleTags === true) {
268 13
      $this->stripOriginalStyleTags($xPath);
269 13
    }
270
271
    // cleanup the HTML if we need to
272 52
    if (true === $this->cleanup) {
273 3
      $this->cleanupHTML($xPath);
274 3
    }
275
276
    // should we output XHTML?
277 52
    if (true === $outputXHTML) {
278 6
      return $dom->xml();
279
    }
280
281
    // just regular HTML 4.01 as it should be used in newsletters
282 47
    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 32
  public function getCssFromInlineHtmlStyleBlock($html)
293
  {
294
    // init var
295 32
    $css = '';
296 32
    $matches = array();
297
298
    // match the style blocks
299 32
    preg_match_all(self::$styleTagRegEx, $html, $matches);
300
301
    // any style-blocks found?
302 32
    if (!empty($matches[1])) {
303
      // add
304 31
      foreach ($matches[1] as $match) {
305 31
        $css .= trim($match) . "\n";
306 31
      }
307 31
    }
308
309 32
    return $css;
310
  }
311
312
  /**
313
   * Process the loaded CSS
314
   *
315
   * @param string $css
316
   *
317
   * @return array
318
   */
319 52
  private function processCSS($css)
320
  {
321
    //reset current set of rules
322 52
    $cssRules = array();
323
324
    // init vars
325 52
    $css = (string)$css;
326
327 52
    $css = $this->doCleanup($css);
328
329
    // rules are splitted by }
330 52
    $rules = (array)explode('}', $css);
331
332
    // init var
333 52
    $i = 1;
334
335
    // loop rules
336 52
    foreach ($rules as $rule) {
337
      // split into chunks
338 52
      $chunks = explode('{', $rule);
339
340
      // invalid rule?
341 52
      if (!isset($chunks[1])) {
342 52
        continue;
343
      }
344
345
      // set the selectors
346 39
      $selectors = trim($chunks[0]);
347
348
      // get cssProperties
349 39
      $cssProperties = trim($chunks[1]);
350
351
      // split multiple selectors
352 39
      $selectors = (array)explode(',', $selectors);
353
354
      // loop selectors
355 39
      foreach ($selectors as $selector) {
356
        // cleanup
357 39
        $selector = trim($selector);
358
359
        // build an array for each selector
360 39
        $ruleSet = array();
361
362
        // store selector
363 39
        $ruleSet['selector'] = $selector;
364
365
        // process the properties
366 39
        $ruleSet['properties'] = $this->processCSSProperties($cssProperties);
367
368
        // calculate specificity
369 39
        $ruleSet['specificity'] = Specificity::fromSelector($selector);
370
371
        // remember the order in which the rules appear
372 39
        $ruleSet['order'] = $i;
373
374
        // add into rules
375 39
        $cssRules[] = $ruleSet;
376
377
        // increment
378 39
        $i++;
379 39
      }
380 52
    }
381
382
    // sort based on specificity
383 52
    if (0 !== count($cssRules)) {
384 39
      usort($cssRules, array(__CLASS__, 'sortOnSpecificity'));
385 39
    }
386
387 52
    return $cssRules;
388
  }
389
390
  /**
391
   * @param string $css
392
   *
393
   * @return string
394
   */
395 52
  private function doCleanup($css)
396
  {
397
    // remove newlines & replace double quotes by single quotes
398 52
    $css = str_replace(
399 52
        array("\r", "\n", '"'),
400 52
        array('', '', '\''),
401
        $css
402 52
    );
403
404
    // remove comments
405 52
    $css = preg_replace(self::$styleCommentRegEx, '', $css);
406
407
    // remove spaces
408 52
    $css = preg_replace('/\s\s+/', ' ', $css);
409
410
    // remove css charset
411 52
    if (true === $this->excludeCssCharset) {
412 52
      $css = $this->stripeCharsetInCss($css);
413 52
    }
414
415
    // remove css media queries
416 52
    if (true === $this->excludeMediaQueries) {
417 51
      $css = $this->stripeMediaQueries($css);
418 51
    }
419
420 52
    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 51
  private function stripeMediaQueries($css)
431
  {
432
    // remove comments previously to matching media queries
433 51
    $css = preg_replace(self::$styleCommentRegEx, '', $css);
434
435 51
    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 52
  private function stripeCharsetInCss($css)
446
  {
447 52
    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 39
  private function processCSSProperties($propertyString)
458
  {
459
    // split into chunks
460 39
    $properties = $this->splitIntoProperties($propertyString);
461
462
    // init var
463 39
    $pairs = array();
464
465
    // loop properties
466 39
    foreach ($properties as $property) {
467
      // split into chunks
468 39
      $chunks = (array)explode(':', $property, 2);
469
470
      // validate
471 39
      if (!isset($chunks[1])) {
472 33
        continue;
473
      }
474
475
      // cleanup
476 38
      $chunks[0] = trim($chunks[0]);
477 38
      $chunks[1] = trim($chunks[1]);
478
479
      // add to pairs array
480
      if (
481 38
          !isset($pairs[$chunks[0]])
482 38
          ||
483 5
          !in_array($chunks[1], $pairs[$chunks[0]], true)
484 38
      ) {
485 38
        $pairs[$chunks[0]][] = $chunks[1];
486 38
      }
487 39
    }
488
489
    // sort the pairs
490 39
    ksort($pairs);
491
492
    // return
493 39
    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 39
  private function splitIntoProperties($styles)
505
  {
506 39
    $properties = (array)explode(';', $styles);
507 39
    $propertiesCount = count($properties);
508
509
    /** @noinspection ForeachInvariantsInspection */
510 39
    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 39
          isset($properties[$i + 1])
515 39
          &&
516 32
          strpos($properties[$i + 1], 'base64,') !== false
517 39
      ) {
518 1
        $properties[$i] .= ';' . $properties[$i + 1];
519 1
        $properties[$i + 1] = '';
520 1
        ++$i;
521 1
      }
522 39
    }
523
524 39
    return $properties;
525
  }
526
527
  /**
528
   * create XPath
529
   *
530
   * @param \DOMDocument $document
531
   * @param array        $cssRules
532
   *
533
   * @return \DOMXPath
534
   */
535 52
  private function createXPath(\DOMDocument $document, array $cssRules)
536
  {
537 52
    $propertyStorage = new \SplObjectStorage();
538 52
    $xPath = new \DOMXPath($document);
539
540
    // any rules?
541 52
    if (0 !== count($cssRules)) {
542
      // loop rules
543 39
      foreach ($cssRules as $rule) {
544
545 39
        $ruleSelector = $rule['selector'];
546 39
        $ruleProperties = $rule['properties'];
547
548 39
        if (!$ruleSelector || !$ruleProperties) {
549 3
          continue;
550
        }
551
552
        try {
553 38
          $query = $this->cssConverter->toXPath($ruleSelector);
554 38
        } catch (ExceptionInterface $e) {
555 5
          $query = null;
556
        }
557
558
        // validate query
559 38
        if (null === $query) {
560 5
          continue;
561
        }
562
563
        // search elements
564 37
        $elements = $xPath->query($query);
565
566
        // validate elements
567 37
        if (false === $elements) {
568
          continue;
569
        }
570
571
        // loop found elements
572 37
        foreach ($elements as $element) {
573
574
          /**
575
           * @var $element \DOMElement
576
           */
577
578
          if (
579
              $ruleSelector == '*'
580 37
              &&
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 1
                  || $element->tagName == 'link'
589 1
              )
590 37
          ) {
591 1
            continue;
592
          }
593
594
          // no styles stored?
595 37
          if (!isset($propertyStorage[$element])) {
596
597
            // init var
598 37
            $originalStyle = $element->attributes->getNamedItem('style');
599
600 37
            if ($originalStyle) {
601 11
              $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 11
            } else {
603 35
              $originalStyle = '';
604
            }
605
606
            // store original styles
607 37
            $propertyStorage->attach($element, $originalStyle);
608
609
            // clear the styles
610 37
            $element->setAttribute('style', '');
611 37
          }
612
613
          // set attribute
614 37
          $propertiesString = $this->createPropertyChunks($element, $ruleProperties);
615 37
          if ($propertiesString) {
616 37
            $element->setAttribute('style', $propertiesString);
617 37
          }
618 37
        }
619 39
      }
620
621 39
      foreach ($propertyStorage as $element) {
622 37
        $originalStyle = $propertyStorage->getInfo();
623 37
        if ($originalStyle) {
624 11
          $originalStyles = $this->splitIntoProperties($originalStyle);
625 11
          $originalProperties = $this->splitStyleIntoChunks($originalStyles);
626
627
          // set attribute
628 11
          $propertiesString = $this->createPropertyChunks($element, $originalProperties);
629 11
          if ($propertiesString) {
630 11
            $element->setAttribute('style', $propertiesString);
631 11
          }
632 11
        }
633 39
      }
634 39
    }
635
636 52
    return $xPath;
637
  }
638
639
  /**
640
   * @param \DOMElement $element
641
   * @param array       $ruleProperties
642
   *
643
   * @return string
644
   */
645 37
  private function createPropertyChunks(\DOMElement $element, array $ruleProperties)
646
  {
647
    // init var
648 37
    $properties = array();
649
650
    // get current styles
651 37
    $stylesAttribute = $element->attributes->getNamedItem('style');
652
653
    // any styles defined before?
654 37
    if (null !== $stylesAttribute) {
655
      // get value for the styles attribute
656 37
      $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 37
      $definedProperties = $this->splitIntoProperties($definedStyles);
660
661 37
      $properties = $this->splitStyleIntoChunks($definedProperties);
662 37
    }
663
664
    // add new properties into the list
665 37
    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 37
          !isset($properties[$key])
670 37
          ||
671 12
          false === stripos($properties[$key], '!important')
672 12
          ||
673 7
          false !== stripos(implode('', (array)$value), '!important')
674 37
      ) {
675 37
        unset($properties[$key]);
676 37
        $properties[$key] = $value;
677 37
      }
678 37
    }
679
680
    // build string
681 37
    $propertyChunks = array();
682
683
    // build chunks
684 37
    foreach ($properties as $key => $values) {
685 37
      foreach ((array)$values as $value) {
686 37
        $propertyChunks[] = $key . ': ' . $value . ';';
687 37
      }
688 37
    }
689
690 37
    return implode(' ', $propertyChunks);
691
  }
692
693
  /**
694
   * @param array $definedProperties
695
   *
696
   * @return array
697
   */
698 37
  private function splitStyleIntoChunks(array $definedProperties)
699
  {
700
    // init var
701 37
    $properties = array();
702
703
    // loop properties
704 37
    foreach ($definedProperties as $property) {
705
      // validate property
706
      if (
707
          !$property
708 37
          ||
709 19
          strpos($property, ':') === false
710 37
      ) {
711 37
        continue;
712
      }
713
714
      // split into chunks
715 19
      $chunks = (array)explode(':', trim($property), 2);
716
717
      // validate
718 19
      if (!isset($chunks[1])) {
719
        continue;
720
      }
721
722
      // loop chunks
723 19
      $properties[$chunks[0]] = trim($chunks[1]);
724 37
    }
725
726 37
    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 11
      } else {
751
        // remove the entire style tag
752 1
        $node->parentNode->removeChild($node);
753
      }
754 13
    }
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 3
    }
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 30
  public function setUseInlineStylesBlock($on = true)
810
  {
811 30
    $this->useInlineStylesBlock = (bool)$on;
812
813 30
    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