1 <?php 2 3 namespace Sabberworm\CSS; 4 5 use Sabberworm\CSS\Parsing\OutputException; 6 7 class OutputFormatter 8 { 9 /** 10 * @var OutputFormat 11 */ 12 private $oFormat; 13 14 public function __construct(OutputFormat $oFormat) 15 { 16 $this->oFormat = $oFormat; 17 } 18 19 /** 20 * @param string $sName 21 * @param string|null $sType 22 * 23 * @return string 24 */ 25 public function space($sName, $sType = null) 26 { 27 $sSpaceString = $this->oFormat->get("Space$sName"); 28 // If $sSpaceString is an array, we have multiple values configured 29 // depending on the type of object the space applies to 30 if (is_array($sSpaceString)) { 31 if ($sType !== null && isset($sSpaceString[$sType])) { 32 $sSpaceString = $sSpaceString[$sType]; 33 } else { 34 $sSpaceString = reset($sSpaceString); 35 } 36 } 37 return $this->prepareSpace($sSpaceString); 38 } 39 40 /** 41 * @return string 42 */ 43 public function spaceAfterRuleName() 44 { 45 return $this->space('AfterRuleName'); 46 } 47 48 /** 49 * @return string 50 */ 51 public function spaceBeforeRules() 52 { 53 return $this->space('BeforeRules'); 54 } 55 56 /** 57 * @return string 58 */ 59 public function spaceAfterRules() 60 { 61 return $this->space('AfterRules'); 62 } 63 64 /** 65 * @return string 66 */ 67 public function spaceBetweenRules() 68 { 69 return $this->space('BetweenRules'); 70 } 71 72 /** 73 * @return string 74 */ 75 public function spaceBeforeBlocks() 76 { 77 return $this->space('BeforeBlocks'); 78 } 79 80 /** 81 * @return string 82 */ 83 public function spaceAfterBlocks() 84 { 85 return $this->space('AfterBlocks'); 86 } 87 88 /** 89 * @return string 90 */ 91 public function spaceBetweenBlocks() 92 { 93 return $this->space('BetweenBlocks'); 94 } 95 96 /** 97 * @return string 98 */ 99 public function spaceBeforeSelectorSeparator() 100 { 101 return $this->space('BeforeSelectorSeparator'); 102 } 103 104 /** 105 * @return string 106 */ 107 public function spaceAfterSelectorSeparator() 108 { 109 return $this->space('AfterSelectorSeparator'); 110 } 111 112 /** 113 * @param string $sSeparator 114 * 115 * @return string 116 */ 117 public function spaceBeforeListArgumentSeparator($sSeparator) 118 { 119 return $this->space('BeforeListArgumentSeparator', $sSeparator); 120 } 121 122 /** 123 * @param string $sSeparator 124 * 125 * @return string 126 */ 127 public function spaceAfterListArgumentSeparator($sSeparator) 128 { 129 return $this->space('AfterListArgumentSeparator', $sSeparator); 130 } 131 132 /** 133 * @return string 134 */ 135 public function spaceBeforeOpeningBrace() 136 { 137 return $this->space('BeforeOpeningBrace'); 138 } 139 140 /** 141 * Runs the given code, either swallowing or passing exceptions, depending on the `bIgnoreExceptions` setting. 142 * 143 * @param string $cCode the name of the function to call 144 * 145 * @return string|null 146 */ 147 public function safely($cCode) 148 { 149 if ($this->oFormat->get('IgnoreExceptions')) { 150 // If output exceptions are ignored, run the code with exception guards 151 try { 152 return $cCode(); 153 } catch (OutputException $e) { 154 return null; 155 } // Do nothing 156 } else { 157 // Run the code as-is 158 return $cCode(); 159 } 160 } 161 162 /** 163 * Clone of the `implode` function, but calls `render` with the current output format instead of `__toString()`. 164 * 165 * @param string $sSeparator 166 * @param array<array-key, Renderable|string> $aValues 167 * @param bool $bIncreaseLevel 168 * 169 * @return string 170 */ 171 public function implode($sSeparator, array $aValues, $bIncreaseLevel = false) 172 { 173 $sResult = ''; 174 $oFormat = $this->oFormat; 175 if ($bIncreaseLevel) { 176 $oFormat = $oFormat->nextLevel(); 177 } 178 $bIsFirst = true; 179 foreach ($aValues as $mValue) { 180 if ($bIsFirst) { 181 $bIsFirst = false; 182 } else { 183 $sResult .= $sSeparator; 184 } 185 if ($mValue instanceof Renderable) { 186 $sResult .= $mValue->render($oFormat); 187 } else { 188 $sResult .= $mValue; 189 } 190 } 191 return $sResult; 192 } 193 194 /** 195 * @param string $sString 196 * 197 * @return string 198 */ 199 public function removeLastSemicolon($sString) 200 { 201 if ($this->oFormat->get('SemicolonAfterLastRule')) { 202 return $sString; 203 } 204 $sString = explode(';', $sString); 205 if (count($sString) < 2) { 206 return $sString[0]; 207 } 208 $sLast = array_pop($sString); 209 $sNextToLast = array_pop($sString); 210 array_push($sString, $sNextToLast . $sLast); 211 return implode(';', $sString); 212 } 213 214 /** 215 * @param string $sSpaceString 216 * 217 * @return string 218 */ 219 private function prepareSpace($sSpaceString) 220 { 221 return str_replace("\n", "\n" . $this->indent(), $sSpaceString); 222 } 223 224 /** 225 * @return string 226 */ 227 private function indent() 228 { 229 return str_repeat($this->oFormat->sIndentation, $this->oFormat->level()); 230 } 231 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body