Changeset 2711273
- Timestamp:
- 04/18/2022 10:21:54 PM (4 years ago)
- Location:
- torque/trunk
- Files:
-
- 2 added
- 10 edited
-
packages/cssdoc/cssdoc.php (modified) (2 diffs)
-
packages/htmldoc/autoload.php (modified) (1 diff)
-
packages/htmldoc/helpers (added)
-
packages/htmldoc/helpers/selector.php (added)
-
packages/htmldoc/htmldoc.php (modified) (14 diffs)
-
packages/htmldoc/tokens/comment.php (modified) (1 diff)
-
packages/htmldoc/tokens/custom.php (modified) (1 diff)
-
packages/htmldoc/tokens/tag.php (modified) (18 diffs)
-
packages/htmldoc/tokens/text.php (modified) (2 diffs)
-
packages/jslite/jslite.php (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
-
torque.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
torque/trunk/packages/cssdoc/cssdoc.php
r2693063 r2711273 457 457 458 458 /** 459 * Compile the propertyto a string460 * 461 * @param array $options An array of compilation options459 * Compile the document to a string 460 * 461 * @param array $options An array indicating output options, this is merged with cssdoc::$output 462 462 * @return void 463 463 */ … … 468 468 469 469 /** 470 * Compile the document as an HTML string and save it to the specified location 471 * 472 * @param array $options An array indicating output options, this is merged with htmldoc::$output 473 * @return string The compiled HTML 470 * Compile the document and save it to the specified location 471 * 472 * @param string|null $file The file location to save the document to, or null to just return the compiled code 473 * @param array $options An array indicating output options, this is merged with cssdoc::$output 474 * @return string|bool The compiled CSS, or false if the file could not be saved 474 475 */ 475 476 public function save(string $file = null, array $options = []) { 476 477 $css = $this->compile($options); 477 478 479 // save file 480 if ($file && \file_put_contents($file, $css) === false) { 481 \trigger_error('File could not be written', E_USER_WARNING); 482 return false; 483 } 484 478 485 // send back as string 479 if (!$file) { 480 return $css; 481 482 // save file 483 } elseif (\file_put_contents($file, $css) === false) { 484 \trigger_error('File could not be written', E_USER_WARNING); 485 } else { 486 return true; 487 } 488 return false; 486 return $css; 489 487 } 490 488 -
torque/trunk/packages/htmldoc/autoload.php
r2592945 r2711273 11 11 'hexydec\\html\\custom' => __DIR__.'/tokens/custom.php', 12 12 'hexydec\\html\\tag' => __DIR__.'/tokens/tag.php', 13 'hexydec\\html\\text' => __DIR__.'/tokens/text.php' 13 'hexydec\\html\\text' => __DIR__.'/tokens/text.php', 14 'hexydec\\html\\selector' => __DIR__.'/helpers/selector.php' 14 15 ]; 15 16 if (isset($classes[$class])) { -
torque/trunk/packages/htmldoc/htmldoc.php
r2693063 r2711273 4 4 use \hexydec\tokens\tokenise; 5 5 6 /** 7 * @property array $config 8 * @property-read int $length 9 */ 6 10 class htmldoc extends config implements \ArrayAccess, \Iterator { 7 11 … … 89 93 */ 90 94 public function offsetSet($i, $value) : void { 91 if (\is_null($i)) { 92 $this->children[] = $value; 93 } else { 94 $this->children[$i] = $value; 95 } 95 $this->children[$i] = $value; 96 96 } 97 97 … … 119 119 * 120 120 * @param string|integer $i The key to be accessed, can be a string or integer 121 * @return mixed The requested value or null if the key doesn't exist 122 */ 123 public function offsetGet(mixed $i) : mixed { // return reference so you can set it like an array 124 return $this->children[$i] ?? null; 121 * @return htmldoc|null The child node at the requested position or null if there is no child at the requested position 122 */ 123 public function offsetGet(mixed $i) : ?htmldoc { // return reference so you can set it like an array 124 if (isset($this->children[$i])) { 125 $obj = new htmldoc($this->config); 126 $obj->collection([$this->children[$i]]); 127 return $obj; 128 } 129 return null; 125 130 } 126 131 … … 128 133 * Retrieve the document node in the current position 129 134 * 130 * @return tag|text|comment|doctype The child node at the current pointer position 131 */ 132 public function current() : mixed { 133 return $this->children[$this->pointer] ?? null; 135 * @return htmldoc|null The child node at the current pointer position or null if there are no children 136 */ 137 public function current() : ?htmldoc { 138 if (isset($this->children[$this->pointer])) { 139 $obj = new htmldoc($this->config); 140 $obj->collection([$this->children[$this->pointer]]); 141 return $obj; 142 } 143 return null; 134 144 } 135 145 … … 198 208 $charset = null; 199 209 $meta = \stream_get_meta_data($handle); 200 if (!empty($meta['wrapper_data'])) { 201 foreach ($meta['wrapper_data'] AS $item) { 202 if (\mb_stripos($item, 'Content-Type:') === 0 && ($value = \mb_stristr($item, 'charset=')) !== false) { 203 $charset = \mb_substr($value, 8); 204 break; 205 } 210 foreach ($meta['wrapper_data'] ?? [] AS $item) { 211 if (\mb_stripos($item, 'Content-Type:') === 0 && ($value = \mb_stristr($item, 'charset=')) !== false) { 212 $charset = \mb_substr($value, 8); 213 break; 206 214 } 207 215 } … … 252 260 */ 253 261 protected function getCharsetFromHtml(string $html) : ?string { 254 if (\preg_match('/<meta[^>]+charset[^>]+>/i', $html, $match)) { 255 $obj = new htmldoc($this->config); 256 if ($obj->load($match[0], \mb_internal_encoding())) { 257 258 // <meta charset="xxx" /> 259 if (($charset = $obj->attr('charset')) !== null && $this->isEncodingValid($charset)) { 262 $obj = new htmldoc($this->config); 263 $pat = '/<meta[^>]+charset[^>]+>/i'; 264 if (\preg_match($pat, $html, $match) && $obj->load($match[0], \mb_internal_encoding())) { 265 266 // <meta charset="xxx" /> 267 if (($charset = $obj->attr('charset')) !== null && $this->isEncodingValid($charset)) { 268 return $charset; 269 270 // <meta http-equiv="Content-Type" content="text/html; charset=xxx" /> 271 } elseif (($value = $obj->eq(0)->attr('content')) !== null && ($charset = \mb_stristr($value, 'charset=')) !== false) { 272 $charset = \mb_substr($charset, 8); 273 if ($this->isEncodingValid($charset)) { 260 274 return $charset; 261 262 // <meta http-equiv="Content-Type" content="text/html; charset=xxx" />263 } elseif (($value = $obj->eq(0)->attr('content')) !== null && ($charset = \mb_stristr($value, 'charset=')) !== false) {264 $charset = \mb_substr($charset, 8);265 if ($this->isEncodingValid($charset)) {266 return $charset;267 }268 275 } 269 276 } … … 309 316 310 317 /** 311 * Parses a CSS selector string312 *313 * @param string $selector The CSS selector string to parse314 * @return array|bool An array of selector components315 */316 protected function parseSelector(tokenise $tokens) {317 if (($token = $tokens->next()) !== null) {318 $selectors = $parts = [];319 $join = null;320 do {321 switch ($token['type']) {322 case 'id':323 $parts[] = [324 'id' => \mb_substr($token['value'], 1),325 'join' => $join326 ];327 $join = null;328 break;329 330 case 'class':331 $parts[] = [332 'class' => \mb_substr($token['value'], 1),333 'join' => $join334 ];335 $join = null;336 break;337 338 case 'string':339 $parts[] = [340 'tag' => $token['value'],341 'join' => $join342 ];343 $join = null;344 break;345 346 case 'squareopen':347 $item = ['join' => $join, 'sensitive' => true];348 while (($token = $tokens->next()) !== null) {349 if ($token['type'] === 'squareclose') {350 break;351 } elseif (\in_array($token['type'], ['string', 'quotes'], true)) {352 if ($token['type'] === 'quotes') {353 $token['value'] = \stripslashes(\mb_substr($token['value'], 1, -1));354 }355 if (!isset($item['attribute'])) {356 $item['attribute'] = $token['value'];357 } elseif (!isset($item['value'])) {358 $item['value'] = $token['value'];359 } elseif ($token['value'] === 'i') {360 $item['sensitive'] = false;361 }362 } elseif ($token['type'] === 'comparison') {363 $item['comparison'] = $token['value'];364 }365 }366 $parts[] = $item;367 $join = null;368 break;369 370 case 'pseudo':371 $sub = null;372 if (($bracket = $tokens->next()) !== null && $bracket['type'] === 'bracketopen') {373 $sub = $this->parseSelector($tokens);374 } elseif ($bracket) {375 $tokens->prev();376 }377 $parts[] = [378 'pseudo' => \mb_substr($token['value'], 1),379 'sub' => $sub,380 'join' => $join381 ];382 $join = null;383 break;384 385 case 'join':386 $join = \trim($token['value']);387 break;388 389 case 'whitespace':390 if ($parts) {391 $join = ' ';392 }393 break;394 395 case 'comma':396 $selectors[] = $parts;397 $parts = [];398 break;399 400 case 'bracketclose':401 $selectors[] = $parts;402 $parts = [];403 break;404 }405 } while (($token = $tokens->next()) !== null);406 if ($parts) {407 $selectors[] = $parts;408 }409 return $selectors;410 }411 return false;412 }413 414 /**415 318 * Caches the input values and records the number of occurences 416 319 * … … 476 379 */ 477 380 public function find(string $selector) : htmldoc { 478 $ tokens = new tokenise(self::$selectors, \trim($selector));381 $obj = new selector(); 479 382 480 383 // parse selector and find tags 481 384 $found = []; 482 if (($ parsed = $this->parseSelector($tokens)) !== false) {385 if (($tokens = $obj->get($selector)) !== false) { 483 386 foreach ($this->children AS $item) { 484 387 if (\get_class($item) === 'hexydec\\html\\tag') { 485 foreach ($ parsedAS $value) {388 foreach ($tokens AS $value) { 486 389 if (($items = $item->find($value)) !== false) { 487 390 $found = \array_merge($found, $items); … … 629 532 630 533 // sort classes by occurence, then by string 631 if (\is_array($minify['attributes'])) { 632 633 // sort attribute values by most frequent 634 if ($minify['attributes']['sort'] && !empty($this->cache['attr'])) { 635 \arsort($this->cache['attr'], SORT_NUMERIC); 636 \arsort($this->cache['attrvalues'], SORT_NUMERIC); 637 $attr = []; 638 foreach ($this->cache['attrvalues'] AS $item => $occurences) { 639 if ($occurences > 5) { 640 $item = \mb_strstr($item, '=', true); 641 if (!\in_array($item, $attr, true)) { 642 $attr[] = $item; 643 } 644 } else { 645 break; 646 } 647 } 648 $minify['attributes']['sort'] = \array_unique(\array_merge($attr, \array_keys($this->cache['attr']))); 649 } 534 if (!empty($minify['attributes']['sort']) && !empty($this->cache['attr'])) { 535 $minify['attributes']['sort'] = $this->sortAttributes($this->cache['attr'], $this->cache['attrvalues']); 650 536 } 651 537 … … 654 540 $item->minify($minify); 655 541 } 542 } 543 544 /** 545 * Sort attributes in frequency order 546 * 547 * @param array $attr An array of attribute keys 548 * @param array $values An array of attribute values 549 * @return array An array of attributes ordered by frequency 550 */ 551 protected function sortAttributes(array $attr, array $values) : array { 552 \arsort($attr, SORT_NUMERIC); 553 \arsort($values, SORT_NUMERIC); 554 $items = []; 555 foreach ($values AS $item => $occurences) { 556 if ($occurences > 5) { 557 $item = \mb_strstr($item, '=', true); 558 if (!\in_array($item, $items, true)) { 559 $items[] = $item; 560 } 561 } else { 562 break; 563 } 564 } 565 return \array_unique(\array_merge($items, \array_keys($attr))); 656 566 } 657 567 … … 767 677 * Compile the document as an HTML string and save it to the specified location 768 678 * 679 * @param string|null $file The file location to save the document to, or null to just return the compiled code 769 680 * @param array $options An array indicating output options, this is merged with htmldoc::$output 770 * @return string The compiled HTML681 * @return string|bool The compiled HTML, or false if the file could not be saved 771 682 */ 772 683 public function save(string $file = null, array $options = []) { … … 784 695 785 696 // convert to target charset 786 $html = \mb_convert_encoding($html, $options['charset']); 787 } 788 789 // send back as string 790 if (!$file) { 791 return $html; 697 $html = (string) \mb_convert_encoding($html, $options['charset']); 698 } 792 699 793 700 // save file 794 } elseif (\file_put_contents($file, $html) === false) {701 if ($file && \file_put_contents($file, $html) === false) { 795 702 \trigger_error('File could not be written', E_USER_WARNING); 796 } else { 797 return true; 798 } 799 return false; 703 return false; 704 } 705 return $html; 800 706 } 801 707 … … 814 720 $str .= \chr($i); 815 721 } 816 $str = \mb_convert_encoding($str, \mb_internal_encoding(), $charset);722 $str = (string) \mb_convert_encoding($str, \mb_internal_encoding(), $charset); 817 723 818 724 // build html entities conversion map … … 826 732 827 733 // convert entities 828 $html = \mb_convert_encoding($html, 'HTML-ENTITIES');734 $html = (string) \mb_convert_encoding($html, 'HTML-ENTITIES'); 829 735 return \str_replace(\array_values($replace), \array_keys($replace), $html); 830 736 } -
torque/trunk/packages/htmldoc/tokens/comment.php
r2693063 r2711273 40 40 */ 41 41 public function minify(array $minify) : void { 42 if (!empty($minify['comments']['remove']) && (empty($minify['comments']['ie']) || (\mb_strpos($this->content, '[if ') !== 0 && $this->content !== '<![endif]'))) { 43 $this->content = null; 42 if (!empty($minify['comments']['remove']) && $this->content) { 43 if (empty($minify['comments']['ie']) || (\mb_strpos($this->content, '[if ') !== 0 && $this->content !== '<![endif]')) { 44 $this->content = null; 45 } 44 46 } 45 47 } -
torque/trunk/packages/htmldoc/tokens/custom.php
r2693063 r2711273 28 28 */ 29 29 public function __construct(htmldoc $root, string $tagName = null) { 30 $this->tagName = $tagName = \mb_strtolower($tagName );30 $this->tagName = $tagName = \mb_strtolower($tagName ?? ''); 31 31 $this->config = $root->config['custom'][$tagName]; 32 32 } -
torque/trunk/packages/htmldoc/tokens/tag.php
r2693063 r2711273 4 4 use \hexydec\tokens\tokenise; 5 5 6 /** 7 * @property tag|null $parent 8 * @property htmldoc $root 9 * @property array $config 10 * @property tag|null $parent 11 * @property array $parenttags 12 * @property string|null $tagName 13 * @property array $attributes 14 * @property string|null $singleton 15 * @property array $children 16 */ 6 17 class tag implements token { 7 18 … … 17 28 18 29 /** 19 * @var tag The parent tag object30 * @var tag|null The parent tag object 20 31 */ 21 32 protected ?tag $parent = null; … … 24 35 * @var array Cache for the list of parent tags 25 36 */ 26 protected ?array $parenttags = null;37 protected array $parenttags = []; 27 38 28 39 /** … … 37 48 38 49 /** 39 * @var string If the tag is a singleton, this defines the closing string50 * @var string|null If the tag is a singleton, this defines the closing string 40 51 */ 41 52 protected ?string $singleton = null; … … 194 205 */ 195 206 protected function getParentTagNames() : array { 196 if ( !$this->parenttags) {207 if (empty($this->parenttags)) { 197 208 $this->parenttags = $this->parent ? $this->parent->getParentTagNames() : []; 198 if ($this->tagName ) {209 if ($this->tagName !== null) { 199 210 $this->parenttags[] = \mb_strtolower($this->tagName); 200 211 } … … 312 323 // insert the nodes 313 324 if ($index !== null) { 314 $this->chidren =\array_splice($this->children, $index, 0, $clones);325 \array_splice($this->children, $index, 0, $clones); 315 326 } 316 327 } … … 336 347 */ 337 348 protected function getIndex() : ?int { 338 foreach ($this->parent->children() AS $key => $item) { 339 if ($item === $this) { 340 return $key; 349 if ($this->parent) { 350 foreach ($this->parent->children() AS $key => $item) { 351 if ($item === $this) { 352 return $key; 353 } 341 354 } 342 355 } … … 351 364 */ 352 365 public function before(array $nodes) : void { 353 if ( ($index = $this->getIndex()) !== null) {366 if ($this->parent !== null && ($index = $this->getIndex()) !== null) { 354 367 $this->parent->append($nodes, $index); 355 368 } … … 363 376 */ 364 377 public function after(array $nodes) : void { 365 if ( ($index = $this->getIndex()) !== null) {378 if ($this->parent !== null && ($index = $this->getIndex()) !== null) { 366 379 $this->parent->append($nodes, $index + 1); 367 380 } … … 395 408 $config = $this->config; 396 409 $attr = $config['attributes']; 397 if ($minify['lowercase'] ) {410 if ($minify['lowercase'] && $this->tagName) { 398 411 $this->tagName = \mb_strtolower($this->tagName); 399 412 } … … 405 418 $tag = $this->tagName; 406 419 $attributes = $this->attributes; 420 $host = null; 407 421 foreach ($attributes AS $key => $value) { 408 422 … … 434 448 // remove host for own domain 435 449 if ($minify['urls']['host'] && isset($_SERVER['HTTP_HOST'])) { 436 $host ??=['//'.$_SERVER['HTTP_HOST'], $scheme.$_SERVER['HTTP_HOST']];450 $host = $host ?? ['//'.$_SERVER['HTTP_HOST'], $scheme.$_SERVER['HTTP_HOST']]; 437 451 foreach ($host AS $item) { 438 452 … … 542 556 543 557 // work out whether to omit the closing tag 544 if ($minify['close'] && \in_array($tag, $config['elements']['closeoptional']) && ($this->parent->tagName === null || !\in_array($this->parent->tagName, $config['elements']['inline'], true))) {558 if ($minify['close'] && $this->parent !== null && \in_array($tag, $config['elements']['closeoptional']) && ($this->parent->tagName === null || !\in_array($this->parent->tagName, $config['elements']['inline'], true))) { 545 559 $children = $this->parent->toArray(); 546 560 $next = false; … … 571 585 572 586 // if last tag, remove closing tag 573 if ( !$children|| $next) {587 if (empty($children) || $next) { 574 588 $this->close = false; 575 589 } … … 731 745 // match first-child 732 746 case 'first-child': 733 $children = $this->parent ->children();747 $children = $this->parent !== null ? $this->parent->children() : []; 734 748 if (!isset($children[0]) || $this !== $children[0]) { 735 749 $match = false; … … 740 754 // match last child 741 755 case 'last-child': 742 $children = $this->parent ->children();756 $children = $this->parent !== null ? $this->parent->children() : []; 743 757 if (($last = \end($children)) === false || $this !== $last) { 744 758 $match = false; … … 779 793 * @param string $key The key of the attribute whos value you wish to retrieve or update 780 794 * @param string $value The value of the attribute to update 781 * @return string The value of the attrbute or NULL if the attribute does not exist795 * @return string|null The value of the attrbute or NULL if the attribute does not exist 782 796 */ 783 797 public function attr(string $key, ?string $value = null) : ?string { … … 788 802 789 803 // get the value 790 } else if (\array_key_exists($key, $this->attributes)){791 return $this->attributes[$key] === null ? true : $this->attributes[$key];804 } else { 805 return $this->attributes[$key] ?? null; 792 806 } 793 807 return null; -
torque/trunk/packages/htmldoc/tokens/text.php
r2693063 r2711273 12 12 13 13 /** 14 * @var tag The parent tag object14 * @var tag|null The parent tag object 15 15 */ 16 protected tag $parent;16 protected ?tag $parent = null; 17 17 18 18 /** … … 27 27 * @param tag $parent The parent tag object 28 28 */ 29 public function __construct(htmldoc $root, tag $parent = null) {29 public function __construct(htmldoc $root, ?tag $parent = null) { 30 30 $this->root = $root; 31 31 $this->parent = $parent; -
torque/trunk/packages/jslite/jslite.php
r2693063 r2711273 185 185 186 186 /** 187 * Compile the document as an HTML string 188 * 189 * @return string The compiled Javascript 190 */ 191 public function compile() : string { 187 * Compile the document to a string 188 * 189 * @param array $options An array indicating output options 190 * @return void 191 */ 192 public function compile(array $options = []) : string { 192 193 $js = ''; 193 194 foreach ($this->expressions AS $item) { 194 $js .= $item->compile( );195 $js .= $item->compile($options); 195 196 } 196 197 return $js; 197 198 } 199 200 /** 201 * Compile the document and save it to the specified location 202 * 203 * @param string|null $file The file location to save the document to, or null to just return the compiled code 204 * @param array $options An array indicating output options 205 * @return string|bool The compiled Javascript, or false if the file could not be saved 206 */ 207 public function save(string $file = null, array $options = []) { 208 $js = $this->compile($options); 209 210 // save file 211 if ($file && \file_put_contents($file, $js) === false) { 212 \trigger_error('File could not be written', E_USER_WARNING); 213 return false; 214 } 215 216 // send back as string 217 return $js; 218 } 198 219 } -
torque/trunk/readme.txt
r2693063 r2711273 4 4 Requires at least: 5.9 5 5 Tested up to: 5.9 6 Requires PHP: 8.07 Stable tag: 0.6. 06 Requires PHP: 7.4 7 Stable tag: 0.6.1 8 8 License: GPLv3 9 9 License URI: https://www.gnu.org/licenses/gpl-3.0.en.html … … 137 137 == Changelog == 138 138 139 = Version 0.6.1 = 140 141 * Fixed issue where the plugin said it was only compatible with PHP 8.0+, whereas it still supports 7.4 142 * Updated dependencies 143 139 144 = Version 0.6.0 = 140 145 -
torque/trunk/torque.php
r2693063 r2711273 11 11 Description: Make your Wordpress website noticably faster by optimising how it is delivered. Analyse your website's performance and security, minify and combine your assets, and configure an array of performance and security settings quickly and easily with this comprehensive plugin. Achieves the best compression of any minification plugin. 12 12 Version: 0.6.0 13 Requires PHP: 8.013 Requires PHP: 7.4 14 14 Author: Hexydec 15 15 Author URI: https://github.com/hexydec/
Note: See TracChangeset
for help on using the changeset viewer.