Specificity.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. namespace TijsVerkoyen\CssToInlineStyles;
  3. /**
  4. * CSS to Inline Styles Specificity class.
  5. *
  6. * Compare specificity based on the CSS3 spec.
  7. *
  8. * @see http://www.w3.org/TR/selectors/#specificity
  9. *
  10. */
  11. class Specificity
  12. {
  13. /**
  14. * The number of ID selectors in the selector
  15. *
  16. * @var int
  17. */
  18. private $a;
  19. /**
  20. *
  21. * The number of class selectors, attributes selectors, and pseudo-classes in the selector
  22. *
  23. * @var int
  24. */
  25. private $b;
  26. /**
  27. * The number of type selectors and pseudo-elements in the selector
  28. *
  29. * @var int
  30. */
  31. private $c;
  32. /**
  33. * @param int $a The number of ID selectors in the selector
  34. * @param int $b The number of class selectors, attributes selectors, and pseudo-classes in the selector
  35. * @param int $c The number of type selectors and pseudo-elements in the selector
  36. */
  37. public function __construct($a = 0, $b = 0, $c = 0)
  38. {
  39. $this->a = $a;
  40. $this->b = $b;
  41. $this->c = $c;
  42. }
  43. /**
  44. * Increase the current specificity by adding the three values
  45. *
  46. * @param int $a The number of ID selectors in the selector
  47. * @param int $b The number of class selectors, attributes selectors, and pseudo-classes in the selector
  48. * @param int $c The number of type selectors and pseudo-elements in the selector
  49. */
  50. public function increase($a, $b, $c)
  51. {
  52. $this->a += $a;
  53. $this->b += $b;
  54. $this->c += $c;
  55. }
  56. /**
  57. * Get the specificity values as an array
  58. *
  59. * @return array
  60. */
  61. public function getValues()
  62. {
  63. return array($this->a, $this->b, $this->c);
  64. }
  65. /**
  66. * Calculate the specificity based on a CSS Selector string,
  67. * Based on the patterns from premailer/css_parser by Alex Dunae
  68. *
  69. * @see https://github.com/premailer/css_parser/blob/master/lib/css_parser/regexps.rb
  70. * @param string $selector
  71. * @return static
  72. */
  73. public static function fromSelector($selector)
  74. {
  75. $pattern_a = " \#";
  76. $pattern_b = " (\.[\w]+) # classes
  77. |
  78. \[(\w+) # attributes
  79. |
  80. (\:( # pseudo classes
  81. link|visited|active
  82. |hover|focus
  83. |lang
  84. |target
  85. |enabled|disabled|checked|indeterminate
  86. |root
  87. |nth-child|nth-last-child|nth-of-type|nth-last-of-type
  88. |first-child|last-child|first-of-type|last-of-type
  89. |only-child|only-of-type
  90. |empty|contains
  91. ))";
  92. $pattern_c = " ((^|[\s\+\>\~]+)[\w]+ # elements
  93. |
  94. \:{1,2}( # pseudo-elements
  95. after|before
  96. |first-letter|first-line
  97. |selection
  98. )
  99. )";
  100. return new static(
  101. preg_match_all("/{$pattern_a}/ix", $selector, $matches),
  102. preg_match_all("/{$pattern_b}/ix", $selector, $matches),
  103. preg_match_all("/{$pattern_c}/ix", $selector, $matches)
  104. );
  105. }
  106. /**
  107. * Returns <0 when $specificity is greater, 0 when equal, >0 when smaller
  108. *
  109. * @param Specificity $specificity
  110. * @return int
  111. */
  112. public function compareTo(Specificity $specificity)
  113. {
  114. if ($this->a !== $specificity->a) {
  115. return $this->a - $specificity->a;
  116. } elseif ($this->b !== $specificity->b) {
  117. return $this->b - $specificity->b;
  118. } else {
  119. return $this->c - $specificity->c;
  120. }
  121. }
  122. }