[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/s9e/text-formatter/src/Configurator/JavaScript/ -> StylesheetCompressor.php (source)

   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  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1