Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
StylesheetCompressor.php
001 <?php
002
003 /**
004 * @package s9e\TextFormatter
005 * @copyright Copyright (c) 2010-2022 The s9e authors
006 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
007 */
008 namespace s9e\TextFormatter\Configurator\JavaScript;
009
010 use s9e\TextFormatter\Configurator\Helpers\RegexpBuilder;
011 use s9e\TextFormatter\Configurator\JavaScript\Code;
012
013 class StylesheetCompressor
014 {
015 /**
016 * @var string[] List of regular expressions that match strings to deduplicate
017 */
018 protected $deduplicateTargets = [
019 '<xsl:template match="',
020 '</xsl:template>',
021 '<xsl:apply-templates/>',
022 '<param name="allowfullscreen" value="true"/>',
023 '<xsl:value-of select="',
024 '<xsl:copy-of select="@',
025 '<iframe allowfullscreen="" scrolling="no"',
026 'display:block;overflow:hidden;position:relative;padding-bottom:',
027 'display:inline-block;width:100%;max-width:',
028 ' [-:\\w]++="',
029 '\\{[^}]++\\}',
030 '@[-\\w]{4,}+',
031 '(?<=<)[-:\\w]{4,}+',
032 '(?<==")[^"]{4,}+"'
033 ];
034
035 /**
036 * @var array Associative array of string replacements as [match => replace]
037 */
038 protected $dictionary;
039
040 /**
041 * @var string Prefix used for dictionary keys
042 */
043 protected $keyPrefix = '$';
044
045 /**
046 * @var integer Number of bytes each global substitution must save to be considered
047 */
048 public $minSaving = 10;
049
050 /**
051 * @var array Associative array of [string => saving]
052 */
053 protected $savings;
054
055 /**
056 * @var string
057 */
058 protected $xsl;
059
060 /**
061 * Encode given stylesheet into a compact JavaScript representation
062 *
063 * @param string $xsl Original stylesheet
064 * @return string JavaScript representation of the compressed stylesheet
065 */
066 public function encode($xsl)
067 {
068 $this->xsl = $xsl;
069
070 $this->estimateSavings();
071 $this->filterSavings();
072 $this->buildDictionary();
073
074 $str = $this->getCompressedStylesheet();
075
076 // Split the stylesheet's string into 2000 chars chunks to appease Google Closure Compiler
077 preg_match_all('(.{1,2000})su', $str, $matches);
078
079 $js = implode("+\n", array_map('json_encode', $matches[0]));
080 if (!empty($this->dictionary))
081 {
082 $js = '(' . $js . ').replace(' . $this->getReplacementRegexp() . ',function(k){return' . json_encode($this->dictionary) . '[k];})';
083 }
084
085 return $js;
086 }
087
088 /**
089 * Build a dictionary of all cost-effective string replacements
090 *
091 * @return void
092 */
093 protected function buildDictionary()
094 {
095 $keys = $this->getAvailableKeys();
096 rsort($keys);
097
098 $this->dictionary = [];
099 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 }