[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package s9e\TextFormatter 5 * @copyright Copyright (c) 2010-2022 The s9e authors 6 * @license http://www.opensource.org/licenses/mit-license.php The MIT License 7 */ 8 namespace s9e\TextFormatter\Configurator\JavaScript; 9 10 use s9e\TextFormatter\Configurator\Helpers\RegexpBuilder; 11 use s9e\TextFormatter\Configurator\JavaScript\Code; 12 13 class StylesheetCompressor 14 { 15 /** 16 * @var string[] List of regular expressions that match strings to deduplicate 17 */ 18 protected $deduplicateTargets = [ 19 '<xsl:template match="', 20 '</xsl:template>', 21 '<xsl:apply-templates/>', 22 '<param name="allowfullscreen" value="true"/>', 23 '<xsl:value-of select="', 24 '<xsl:copy-of select="@', 25 '<iframe allowfullscreen="" scrolling="no"', 26 'display:block;overflow:hidden;position:relative;padding-bottom:', 27 'display:inline-block;width:100%;max-width:', 28 ' [-:\\w]++="', 29 '\\{[^}]++\\}', 30 '@[-\\w]{4,}+', 31 '(?<=<)[-:\\w]{4,}+', 32 '(?<==")[^"]{4,}+"' 33 ]; 34 35 /** 36 * @var array Associative array of string replacements as [match => replace] 37 */ 38 protected $dictionary; 39 40 /** 41 * @var string Prefix used for dictionary keys 42 */ 43 protected $keyPrefix = '$'; 44 45 /** 46 * @var integer Number of bytes each global substitution must save to be considered 47 */ 48 public $minSaving = 10; 49 50 /** 51 * @var array Associative array of [string => saving] 52 */ 53 protected $savings; 54 55 /** 56 * @var string 57 */ 58 protected $xsl; 59 60 /** 61 * Encode given stylesheet into a compact JavaScript representation 62 * 63 * @param string $xsl Original stylesheet 64 * @return string JavaScript representation of the compressed stylesheet 65 */ 66 public function encode($xsl) 67 { 68 $this->xsl = $xsl; 69 70 $this->estimateSavings(); 71 $this->filterSavings(); 72 $this->buildDictionary(); 73 74 $str = $this->getCompressedStylesheet(); 75 76 // Split the stylesheet's string into 2000 chars chunks to appease Google Closure Compiler 77 preg_match_all('(.{1,2000})su', $str, $matches); 78 79 $js = implode("+\n", array_map('json_encode', $matches[0])); 80 if (!empty($this->dictionary)) 81 { 82 $js = '(' . $js . ').replace(' . $this->getReplacementRegexp() . ',function(k){return' . json_encode($this->dictionary) . '[k];})'; 83 } 84 85 return $js; 86 } 87 88 /** 89 * Build a dictionary of all cost-effective string replacements 90 * 91 * @return void 92 */ 93 protected function buildDictionary() 94 { 95 $keys = $this->getAvailableKeys(); 96 rsort($keys); 97 98 $this->dictionary = []; 99 arsort($this->savings); 100 foreach (array_keys($this->savings) as $str) 101 { 102 $key = array_pop($keys); 103 if (!$key) 104 { 105 break; 106 } 107 108 $this->dictionary[$key] = $str; 109 } 110 } 111 112 /** 113 * Estimate the savings of every possible string replacement 114 * 115 * @return void 116 */ 117 protected function estimateSavings() 118 { 119 $this->savings = []; 120 foreach ($this->getStringsFrequency() as $str => $cnt) 121 { 122 $len = strlen($str); 123 $originalCost = $cnt * $len; 124 $replacementCost = $cnt * 2; 125 $overhead = $len + 6; 126 127 $this->savings[$str] = $originalCost - ($replacementCost + $overhead); 128 } 129 } 130 131 /** 132 * Filter the savings according to the minSaving property 133 * 134 * @return void 135 */ 136 protected function filterSavings() 137 { 138 $this->savings = array_filter( 139 $this->savings, 140 function ($saving) 141 { 142 return ($saving >= $this->minSaving); 143 } 144 ); 145 } 146 147 /** 148 * Return all the possible dictionary keys that are not present in the original stylesheet 149 * 150 * @return string[] 151 */ 152 protected function getAvailableKeys() 153 { 154 return array_diff($this->getPossibleKeys(), $this->getUnavailableKeys()); 155 } 156 157 /** 158 * Return the stylesheet after dictionary replacements 159 * 160 * @return string 161 */ 162 protected function getCompressedStylesheet() 163 { 164 return strtr($this->xsl, array_flip($this->dictionary)); 165 } 166 167 /** 168 * Return a list of possible dictionary keys 169 * 170 * @return string[] 171 */ 172 protected function getPossibleKeys() 173 { 174 $keys = []; 175 foreach (range('a', 'z') as $char) 176 { 177 $keys[] = $this->keyPrefix . $char; 178 } 179 180 return $keys; 181 } 182 183 /** 184 * Return a regexp that matches all used dictionary keys 185 * 186 * @return string 187 */ 188 protected function getReplacementRegexp() 189 { 190 return '/' . RegexpBuilder::fromList(array_keys($this->dictionary)) . '/g'; 191 } 192 193 /** 194 * Return the frequency of all deduplicatable strings 195 * 196 * @return array Array of [string => frequency] 197 */ 198 protected function getStringsFrequency() 199 { 200 $regexp = '(' . implode('|', $this->deduplicateTargets) . ')S'; 201 preg_match_all($regexp, $this->xsl, $matches); 202 203 return array_count_values($matches[0]); 204 } 205 206 /** 207 * Return the list of possible dictionary keys that appear in the original stylesheet 208 * 209 * @return string[] 210 */ 211 protected function getUnavailableKeys() 212 { 213 preg_match_all('(' . preg_quote($this->keyPrefix) . '.)', $this->xsl, $matches); 214 215 return array_unique($matches[0]); 216 } 217 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |