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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

StylesheetCompressor.php

Zuletzt modifiziert: 02.04.2025, 15:04 - Dateigröße: 4.65 KiB


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  }