See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Autoprefixer. 19 * 20 * This autoprefixer has been developed to satisfy the basic needs of the 21 * theme Boost when working with Bootstrap 4 alpha. We do not recommend 22 * that this tool is shared, nor used outside of this theme. 23 * 24 * @package theme_boost 25 * @copyright 2016 Frédéric Massart - FMCorz.net 26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 */ 28 29 namespace theme_boost; 30 defined('MOODLE_INTERNAL') || die(); 31 32 use Sabberworm\CSS\CSSList\CSSList; 33 use Sabberworm\CSS\CSSList\Document; 34 use Sabberworm\CSS\CSSList\KeyFrame; 35 use Sabberworm\CSS\OutputFormat; 36 use Sabberworm\CSS\Parser; 37 use Sabberworm\CSS\Property\AtRule; 38 use Sabberworm\CSS\Property\Selector; 39 use Sabberworm\CSS\Rule\Rule; 40 use Sabberworm\CSS\RuleSet\AtRuleSet; 41 use Sabberworm\CSS\RuleSet\DeclarationBlock; 42 use Sabberworm\CSS\RuleSet\RuleSet; 43 use Sabberworm\CSS\Settings; 44 use Sabberworm\CSS\Value\CSSFunction; 45 use Sabberworm\CSS\Value\CSSString; 46 use Sabberworm\CSS\Value\PrimitiveValue; 47 use Sabberworm\CSS\Value\RuleValueList; 48 use Sabberworm\CSS\Value\Size; 49 use Sabberworm\CSS\Value\ValueList; 50 51 52 /** 53 * Autoprefixer class. 54 * 55 * Very basic implementation covering simple needs for Bootstrap 4. 56 * 57 * @package theme_boost 58 * @copyright 2016 Frédéric Massart - FMCorz.net 59 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 60 */ 61 class autoprefixer { 62 63 /** @var object The CSS tree. */ 64 protected $tree; 65 66 /** @var string Pseudo classes regex. */ 67 protected $pseudosregex; 68 69 /** @var array At rules prefixes. */ 70 protected static $atrules = [ 71 'keyframes' => ['-webkit-', '-o-'] 72 ]; 73 74 /** @var array Pseudo classes prefixes. */ 75 protected static $pseudos = [ 76 '::placeholder' => ['::-webkit-input-placeholder', '::-moz-placeholder', ':-ms-input-placeholder'] 77 ]; 78 79 /** @var array Rule properties prefixes. */ 80 protected static $rules = [ 81 'animation' => ['-webkit-'], 82 'appearance' => ['-webkit-', '-moz-'], 83 'backface-visibility' => ['-webkit-'], 84 'box-sizing' => ['-webkit-'], 85 'box-shadow' => ['-webkit-'], 86 'background-clip' => ['-webkit-'], 87 'background-size' => ['-webkit-'], 88 'box-shadow' => ['-webkit-'], 89 'column-count' => ['-webkit-', '-moz-'], 90 'column-gap' => ['-webkit-', '-moz-'], 91 'perspective' => ['-webkit-'], 92 'touch-action' => ['-ms-'], 93 'transform' => ['-webkit-', '-moz-', '-ms-', '-o-'], 94 'transition' => ['-webkit-', '-o-'], 95 'transition-timing-function' => ['-webkit-', '-o-'], 96 'transition-duration' => ['-webkit-', '-o-'], 97 'transition-property' => ['-webkit-', '-o-'], 98 'user-select' => ['-webkit-', '-moz-', '-ms-'], 99 ]; 100 101 /** 102 * Constructor. 103 * 104 * @param Document $tree The CSS tree. 105 */ 106 public function __construct(Document $tree) { 107 $this->tree = $tree; 108 109 $pseudos = array_map(function($pseudo) { 110 return '(' . preg_quote($pseudo) . ')'; 111 }, array_keys(self::$pseudos)); 112 $this->pseudosregex = '(' . implode('|', $pseudos) . ')'; 113 } 114 115 /** 116 * Manipulate an array of rules to adapt their values. 117 * 118 * @param array $rules The rules. 119 * @return New array of rules. 120 */ 121 protected function manipulateRuleValues(array $rules) { 122 $finalrules = []; 123 124 foreach ($rules as $rule) { 125 $property = $rule->getRule(); 126 $value = $rule->getValue(); 127 128 if ($property === 'position' && $value === 'sticky') { 129 $newrule = clone $rule; 130 $newrule->setValue('-webkit-sticky'); 131 $finalrules[] = $newrule; 132 133 } else if ($property === 'background-image' && 134 $value instanceof CSSFunction && 135 $value->getName() === 'linear-gradient') { 136 137 foreach (['-webkit-', '-o-'] as $prefix) { 138 $newfunction = clone $value; 139 $newfunction->setName($prefix . $value->getName()); 140 $newrule = clone $rule; 141 $newrule->setValue($newfunction); 142 $finalrules[] = $newrule; 143 } 144 } 145 146 $finalrules[] = $rule; 147 } 148 149 return $finalrules; 150 } 151 152 /** 153 * Prefix all the things! 154 */ 155 public function prefix() { 156 $this->processBlock($this->tree); 157 } 158 159 /** 160 * Process block. 161 * 162 * @param object $block A block. 163 * @param object $parent The parent of the block. 164 */ 165 protected function processBlock($block) { 166 foreach ($block->getContents() as $node) { 167 if ($node instanceof AtRule) { 168 169 $name = $node->atRuleName(); 170 if (isset(self::$atrules[$name])) { 171 foreach (self::$atrules[$name] as $prefix) { 172 $newname = $prefix . $name; 173 $newnode = clone $node; 174 175 if ($node instanceof KeyFrame) { 176 $newnode->setVendorKeyFrame($newname); 177 $block->insert($newnode, $node); 178 179 } else { 180 debugging('Unhandled atRule prefixing.', DEBUG_DEVELOPER); 181 } 182 } 183 } 184 } 185 186 if ($node instanceof CSSList) { 187 $this->processBlock($node); 188 189 } else if ($node instanceof RuleSet) { 190 $this->processDeclaration($node, $block); 191 } 192 } 193 } 194 195 /** 196 * Process declaration. 197 * 198 * @param object $node The declaration block. 199 * @param object $parent The parent. 200 */ 201 protected function processDeclaration($node, $parent) { 202 $rules = []; 203 204 foreach ($node->getRules() as $key => $rule) { 205 $name = $rule->getRule(); 206 $seen[$name] = true; 207 208 if (!isset(self::$rules[$name])) { 209 $rules[] = $rule; 210 continue; 211 } 212 213 foreach (self::$rules[$name] as $prefix) { 214 $newname = $prefix . $name; 215 if (isset($seen[$newname])) { 216 continue; 217 } 218 $newrule = clone $rule; 219 $newrule->setRule($newname); 220 $rules[] = $newrule; 221 } 222 223 $rules[] = $rule; 224 } 225 226 $node->setRules($this->manipulateRuleValues($rules)); 227 228 if ($node instanceof DeclarationBlock) { 229 $selectors = $node->getSelectors(); 230 foreach ($selectors as $key => $selector) { 231 232 $matches = []; 233 if (preg_match($this->pseudosregex, $selector->getSelector(), $matches)) { 234 235 $newnode = clone $node; 236 foreach (self::$pseudos[$matches[1]] as $newpseudo) { 237 $newselector = new Selector(str_replace($matches[1], $newpseudo, $selector->getSelector())); 238 $selectors[$key] = $newselector; 239 $newnode = clone $node; 240 $newnode->setSelectors($selectors); 241 $parent->insert($newnode, $node); 242 } 243 244 // We're only expecting one affected pseudo class per block. 245 break; 246 } 247 } 248 } 249 } 250 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body