diff --git a/README.md b/README.md index 4f918bb..4172aaf 100755 --- a/README.md +++ b/README.md @@ -3,4 +3,4 @@ Minify Extension for [Mecha](https://github.com/mecha-cms/mecha) ![Code Size](https://img.shields.io/github/languages/code-size/mecha-cms/x.minify?color=%23444&style=for-the-badge) -This extension reduces the page size by removing unused white-spaces and comments in the HTML output. \ No newline at end of file +This extension reduces page size by removing unused white-spaces and comments from HTML output. \ No newline at end of file diff --git a/about.page b/about.page index e96510f..fd1af66 100755 --- a/about.page +++ b/about.page @@ -1,6 +1,6 @@ --- title: Minify -description: Removes white-spaces and unused comments in HTML, CSS and JavaScript files. +description: Removes white-spaces and unused comments from CSS, HTML, and JavaScript files. icon: 'M19.5,3.09L20.91,4.5L16.41,9H20V11H13V4H15V7.59L19.5,3.09M20.91,19.5L19.5,20.91L15,16.41V20H13V13H20V15H16.41L20.91,19.5M4.5,3.09L9,7.59V4H11V11H4V9H7.59L3.09,4.5L4.5,3.09M3.09,19.5L7.59,15H4V13H11V20H9V16.41L4.5,20.91L3.09,19.5Z' color: '#534c44' author: Taufik Nurrohman @@ -8,128 +8,46 @@ type: Markdown version: 3.0.0 ... -This extension reduces the page size by removing unused white-spaces and comments in the HTML output. - -~~~ .php -// `Minify::{$any}($in, $comment, $quote)` -[ - '.css' => [2, 2], // `[$comment, $quote]` - '.html' => [2, 1], - '.js' => [2], - '.json' => [], - '.php' => [2] -] -~~~ - -Code | Description ----- | ----------- -`0` | Remove -`1` | Keep -`2` | Remove if/but/when… - -> **Note:** There is no such `0` option for `$quote`. - ---- +This extension reduces page size by removing unused white-spaces and comments from HTML output. ### Usage -#### HTML - -~~~ .xmp.php -Minify::HTML(string $in, int $comment = 2, int $quote = 1): string; -~~~ - -Minify HTML string: - -~~~ .php -echo Minify::HTML(' - - - - Test - - - - -

Test

-

- -

- -'); -~~~ - #### CSS -~~~ .xmp.php -Minify::CSS(string $in, int $comment = 2, int $quote = 2): string; +~~~ .php +Minify::CSS(string $from, int $comment = 2, int $quote = 2): string; ~~~ -Minify CSS string: +#### HTML ~~~ .php -echo Minify::CSS('* { - margin: 0; - padding: 0; - font: inherit; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -/* remove */ - -/*! keep */ - -/** keep */ - -/* @licence keep */ - -/* @license keep */ - -/* @preserve keep */ - -html { - background: #fff; - color: #000; - font: normal normal 16px/1.25 sans-serif; -}'); +Minify::HTML(string $from, int $comment = 2, int $quote = 1): string; ~~~ #### JS -~~~ .xmp.php -Minify::JS(string $in, int $comment = 2, int $quote = 2): string; -~~~ - -Minify JavaScript string: - ~~~ .php -echo Minify::JS('var i, j, k = Date.now(); - -for (i = 0, j = k; i < k; ++i) { - console.log("bark: " + i); -}'); +Minify::JS(string $from, int $comment = 2, int $quote = 2): string; ~~~ #### JSON -~~~ .xmp.php -Minify::JSON(string $in): string; +~~~ .php +Minify::JSON(string $from): string; ~~~ #### PHP -~~~ .xmp.php -Minify::PHP(string $in, int $comment = 2): string; +~~~ .php +Minify::PHP(string $from, int $comment = 2): string; ~~~ ---- - -#### Options +### Options Parameter | Description --------- | ----------- -`$in` | The string input to be minified. -`$comment` | The `$comment` parameter value consists of `0`, `1` and `2`. `0` means remove all comments, `1` means preserve all comments, `2` means remove all comments except special comments like IE conditional comments or license comments. -`$quote` | The `$quote` parameter value consists of `1` and `2`. `1` means preserve all quotes, `2` means remove quotes where possible. \ No newline at end of file +`$from` | The input string to be minified. +`$comment` | The value of the `$comment` parameter consists of `0`, `1`, and `2`. `0` means remove all comments, `1` means preserve all comments, `2` means remove all comments except special comments like IE conditional comments or license comments. +`$quote` | The value of the `$quote` parameter is `1` or `2`. `1` means to preserve all quotes, `2` means to remove quotes where possible. There is no such `0` option for `$quote`. + + *[IE]: Internet Explorer \ No newline at end of file diff --git a/composer.json b/composer.json index 021599a..80e4d23 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "description": "Removes white-spaces and unused comments in HTML, CSS and JavaScript files.", + "description": "Removes white-spaces and unused comments from CSS, HTML, and JavaScript files.", "license": "GPL-3.0-or-later", "name": "mecha-cms/x.minify", "suggest": { diff --git a/engine/plug/minify.php b/engine/plug/minify.php index 4227aeb..13cd2b2 100644 --- a/engine/plug/minify.php +++ b/engine/plug/minify.php @@ -230,24 +230,24 @@ \define(n . "\\token_js_pattern", '/(?:(?![*+?])(?:[^\n\[/\\\]|\\\.|\[(?:[^\n\]\\\]|\\\.)*\])+)/[gimuy]*'); \define(n . "\\token_js_string", '`(?:[^`\\\]|\\\.)*`'); -function every(array $tokens, callable $fn = null, string $in = null, string $flag = 'i') { - if ("" === ($in = \trim($in))) { +function every(array $tokens, callable $fn = null, string $from = null, string $flag = 'i') { + if ("" === ($from = \trim($from))) { return ""; } $pattern = \strtr('(?:' . \implode(')|(?:', $tokens) . ')', ['/' => "\\/"]); - $chops = \preg_split('/(' . $pattern . ')/' . $flag, $in, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); + $chops = \preg_split('/(' . $pattern . ')/' . $flag, $from, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); if (!$fn) { return $chops; } - $out = ""; + $to = ""; while ($chops) { $chop = \array_shift($chops); if ("" === ($token = \trim($chop))) { continue; } - $out .= $fn($token, $chop); + $to .= $fn($token, $chop); } - return $out; + return $to; } function get_css_rules($token) { @@ -528,11 +528,11 @@ function minify_css_values($token, int $quote = 2) { return \substr($token, 1, -1); } -function minify_css(string $in, int $comment = 2, int $quote = 2) { - if ("" === ($in = \trim($in))) { +function minify_css(string $from, int $comment = 2, int $quote = 2) { + if ("" === ($from = \trim($from))) { return ""; } - $out = every([token_css_comment], static function ($token) use ($comment) { + $to = every([token_css_comment], static function ($token) use ($comment) { if (1 === $comment) { return $token; } @@ -555,8 +555,8 @@ function minify_css(string $in, int $comment = 2, int $quote = 2) { return ""; // Remove! } return $token; - }, $in); - $out = every([ + }, $from); + $to = every([ token_css_rules, token_css_comment, '@charset\s+' . token_string . '\s*;', @@ -748,8 +748,8 @@ function minify_css(string $in, int $comment = 2, int $quote = 2) { return $selector . '{' . $block . '}'; } return $token; - }, $out); - return $out; + }, $to); + return $to; } function minify_html_content($token, $tag, $fn, int $quote = 2) { @@ -822,11 +822,15 @@ function minify_html_element($token, int $quote = 2) { return '<' . $name . ("" !== $value ? ' ' . $value : "") . '>'; } -function minify_html(string $in, int $comment = 2, int $quote = 1) { - if ("" === ($in = \trim($in))) { +function minify_html(string $from, int $comment = 2, int $quote = 1) { + if ("" === ($from = \trim($from))) { return ""; } - $out = every([token_html_comment], static function ($token) use ($comment) { + // Hot fix for line break before and/or after flow element(s). Do not remove all of the white-space around them if + // they are surrounded by a plain text node. TODO: Remove this hack in the next release! + $from = \preg_replace('/(' . \strtr(token_html_element_exit, ['/' => "\\/"]) . ')\n([^<])/', '$1 $2', $from); + $from = \preg_replace('/([^>])\n(' . \strtr(token_html_element_enter, ['/' => "\\/"]) . ')/', '$1 $2', $from); + $to = every([token_html_comment], static function ($token) use ($comment) { if (1 === $comment) { return $token; } @@ -849,8 +853,8 @@ function minify_html(string $in, int $comment = 2, int $quote = 1) { return ""; // Remove! } return $token; - }, $in); - $out = every([ + }, $from); + $to = every([ '\s*' . token_html_comment . '\s*', '\s*' . token_html_dtd . '\s*', '\s*' . token_html_pi . '\s*', @@ -918,15 +922,15 @@ function minify_html(string $in, int $comment = 2, int $quote = 1) { return minify_html_element($token, $quote); } return \preg_replace('/\s+/', ' ', $token); - }, $out); - return $out; + }, $to); + return $to; } -function minify_js(string $in, int $comment = 2, int $quote = 2) { - if ("" === ($in = \trim($in))) { +function minify_js(string $from, int $comment = 2, int $quote = 2) { + if ("" === ($from = \trim($from))) { return ""; } - $out = every([ + $to = every([ token_js_comment, token_js_comment_2, token_string, @@ -959,8 +963,8 @@ function minify_js(string $in, int $comment = 2, int $quote = 2) { return ""; // Remove! } return $token; - }, $in); - $out = every([ + }, $from); + $to = every([ token_js_comment, token_js_comment_2, token_string, @@ -997,8 +1001,8 @@ function minify_js(string $in, int $comment = 2, int $quote = 2) { return $chop; } return $token; - }, $out); - $out = every([ + }, $to); + $to = every([ token_js_comment, token_js_comment_2, token_js_pattern, @@ -1032,20 +1036,20 @@ function minify_js(string $in, int $comment = 2, int $quote = 2) { ',}' => '}', ';}' => '}' ]); - }, $out); - return $out; + }, $to); + return $to; } -function minify_json(string $in, int $comment = 2, int $quote = 1) { - return \json_encode(\json_decode($in), \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); +function minify_json(string $from, int $comment = 2, int $quote = 1) { + return \json_encode(\json_decode($from), \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); } -function minify_php(string $in, int $comment = 2, int $quote = 1) { - if ("" === ($in = \trim($in))) { +function minify_php(string $from, int $comment = 2, int $quote = 1) { + if ("" === ($from = \trim($from))) { return ""; } - $out = ""; - $tokens = \token_get_all($in); + $to = ""; + $tokens = \token_get_all($from); foreach ($tokens as $k => $v) { // Peek previous token if (\is_array($prev = $tokens[$k - 1] ?? "")) { @@ -1074,7 +1078,7 @@ function minify_php(string $in, int $comment = 2, int $quote = 1) { ) ) { $v[1] = \ltrim(\substr($v[1], 2, -2), '!*'); - $out .= '/*' . \trim(\strtr($v[1], ['@preserve' => ""])) . '*/'; + $to .= '/*' . \trim(\strtr($v[1], ['@preserve' => ""])) . '*/'; continue; } // Remove comment @@ -1085,29 +1089,29 @@ function minify_php(string $in, int $comment = 2, int $quote = 1) { if ("" === $next) { continue; // Remove the last PHP closing tag } - if (';' === \substr($out, -1)) { - $out = \substr($out, 0, -1); // Remove the last semi-colon before PHP closing tag + if (';' === \substr($to, -1)) { + $to = \substr($to, 0, -1); // Remove the last semi-colon before PHP closing tag } } if (\T_OPEN_TAG === $v[0]) { - $out .= \rtrim($v[1]) . ' '; + $to .= \rtrim($v[1]) . ' '; continue; } if (\T_ECHO === $v[0] || \T_PRINT === $v[0]) { - if ('

text text text

- \ No newline at end of file + + +asdf + keep a space around this element +asdf + +asdf + + remove any space around this element + +asdf + +asdf + remove any space around this element + asdf \ No newline at end of file diff --git a/test/php.txt b/test/php.txt index 317c4a9..caf7990 100755 --- a/test/php.txt +++ b/test/php.txt @@ -56,8 +56,8 @@ use Test\Test\{ Test\Test as Test }; -function css(?string $in) { - return \trim($in); +function css(?string $from) { + return \trim($from); } $var0 = [ 1 , 2 , 3 ] ; // comment