From a8f1ebaff96305b4174e921a87c86bfb65f7c9cb Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Thu, 30 Dec 2021 15:11:56 -0600 Subject: [PATCH 1/7] Revamp the CLI bin and add documentation to the readme --- README.md | 9 +++ bin/minify | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++ bin/minifycss | 45 -------------- bin/minifyjs | 45 -------------- composer.json | 3 +- 5 files changed, 177 insertions(+), 92 deletions(-) create mode 100755 bin/minify delete mode 100755 bin/minifycss delete mode 100755 bin/minifyjs diff --git a/README.md b/README.md index 226b17ce..e4e2d5e9 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,15 @@ echo $minifier->minify(); ``` +### CLI + +``` +vendor/bin/minify /path/to/source/*.css -o /path/to/minified/css/file.css /path/to/source/*.js -o /path/to/minified/js/file.js +``` + +Multiple source files can be passed, both CSS and JS. Define an output file for each file type with the `--output` or `-o` option. If an output file is not defined, the minified contents will be sent to `STDOUT`. + + ## Methods Available methods, for both CSS & JS minifier, are: diff --git a/bin/minify b/bin/minify new file mode 100755 index 00000000..9156a7b0 --- /dev/null +++ b/bin/minify @@ -0,0 +1,167 @@ +#!/usr/bin/env php + 2) $value = $arg_split[2]; + } + + if (array_key_exists($arg, $short_opts)) $arg = $short_opts[$arg]; + + if (in_array($arg, $flag_opts)) { + if (!in_array($arg, $flags)) $flags[] = $arg; + + $last_opt = null; + } else { + if (array_key_exists($arg, $options)) { + if (is_array($options[$arg])) { + $options[$arg][] = $value; + } else { + if (is_null($options[$arg])) { + $options[$arg] = $value; + } elseif (!is_null($value)) { + $options[$arg] = array($options[$arg], $value); + } + } + } else { + $options[$arg] = $value; + } + + $last_opt = $value ? null : $arg; + } + } + + return compact('command', 'arguments', 'options', 'flags'); +} + +// Check PHP setup for CLI arguments +if (!isset($_SERVER['argv']) && !isset($argv)) { + fwrite(STDERR, 'Please enable the "register_argc_argv" directive in your php.ini' . PHP_EOL); + exit(1); +} elseif (!isset($argv)) { + $argv = $_SERVER['argv']; +} + +// Parse CLI arguments +$cli = parse_argv($argv, array( + 'o' => 'output' +)); + +// Check if script run in a CLI environment +if ('cli' !== php_sapi_name()) { + fwrite(STDERR, $cli['command'] . ' must be run in the command line' . PHP_EOL); + exit(1); +} + +// Check if any files were given +if (empty($cli['arguments'])) { + fwrite(STDERR, 'Argument(s) expected: Path to file(s)' . PHP_EOL); + exit(1); +} + +// Check if source files exist +foreach($cli['arguments'] as $source_file) { + if (!file_exists($source_file)) { + fwrite(STDERR, 'Source file "' . $source_file . '" not found' . PHP_EOL); + exit(1); + } +} + +// Get CSS files +$css_files = array_filter($cli['arguments'], function($arg) { + return substr($arg, -4) === '.css'; +}); + +// Get JS files +$js_files = array_filter($cli['arguments'], function($arg) { + return substr($arg, -3) === '.js'; +}); + +// Get output files, if any +$css_output_file = null; +$js_output_file = null; +if (isset($cli['options']['output'])) { + $css_output_files = array_values(array_filter((array) $cli['options']['output'], function($out) { + return substr($out, -4) === '.css'; + })); + + if (!empty($css_output_files)) { + $css_output_file = $css_output_files[0]; + } + + $js_output_files = array_values(array_filter((array) $cli['options']['output'], function($out) { + return substr($out, -3) === '.js'; + })); + + if (!empty($js_output_files)) { + $js_output_file = $js_output_files[0]; + } +} + +try { + if (!empty($css_files)) { + $css_minifier = new Minify\CSS(); + + foreach($css_files as $css_file) { + $css_minifier->add($css_file); + } + + if ($css_output_file) { + $css_minifier->minify($css_output_file); + } else { + echo $css_minifier->minify(); + } + } + + if (!empty($js_files)) { + $js_minifier = new Minify\JS(); + + foreach($js_files as $js_file) { + $js_minifier->add($js_file); + } + + if ($js_output_file) { + $js_minifier->minify($js_output_file); + } else { + echo $js_minifier->minify(); + } + } +} catch (Exception $e) { + fwrite(STDERR, $e->getMessage(), PHP_EOL); + exit(1); +} diff --git a/bin/minifycss b/bin/minifycss deleted file mode 100755 index 6a681a85..00000000 --- a/bin/minifycss +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env php -minify(); -} catch (Exception $e) { - fwrite(STDERR, $e->getMessage(), PHP_EOL); - exit(1); -} diff --git a/bin/minifyjs b/bin/minifyjs deleted file mode 100755 index 4cbe63ff..00000000 --- a/bin/minifyjs +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env php -minify(); -} catch (Exception $e) { - fwrite(STDERR, $e->getMessage(), PHP_EOL); - exit(1); -} diff --git a/composer.json b/composer.json index a6dd4ab6..ae1f2976 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,6 @@ } }, "bin": [ - "bin/minifycss", - "bin/minifyjs" + "bin/minify" ] } From b165519e2b20d7a887c91721b9435c52cc70cd89 Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Thu, 30 Dec 2021 15:40:10 -0600 Subject: [PATCH 2/7] Add gzip option to CLI --- README.md | 5 +++++ bin/minify | 35 +++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e4e2d5e9..ba5917cb 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,11 @@ vendor/bin/minify /path/to/source/*.css -o /path/to/minified/css/file.css /path/ Multiple source files can be passed, both CSS and JS. Define an output file for each file type with the `--output` or `-o` option. If an output file is not defined, the minified contents will be sent to `STDOUT`. +#### Options + + * `--gzip`/`-g` - `gzencode()`s the minified content + * `--output`/`-o` - The file path to write the minified content to + ## Methods diff --git a/bin/minify b/bin/minify index 9156a7b0..5ae2226f 100755 --- a/bin/minify +++ b/bin/minify @@ -78,9 +78,16 @@ if (!isset($_SERVER['argv']) && !isset($argv)) { } // Parse CLI arguments -$cli = parse_argv($argv, array( +$cli = parse_argv( + $argv, + array( + 'g' => 'gzip', 'o' => 'output' -)); + ), + array( + 'gzip' + ) +); // Check if script run in a CLI environment if ('cli' !== php_sapi_name()) { @@ -142,9 +149,17 @@ try { } if ($css_output_file) { - $css_minifier->minify($css_output_file); + if (in_array('gzip', $cli['flags'])) { + $css_minifier->gzip($css_output_file); + } else { + $css_minifier->minify($css_output_file); + } } else { - echo $css_minifier->minify(); + if (in_array('gzip', $cli['flags'])) { + echo $css_minifier->gzip(); + } else { + echo $css_minifier->minify(); + } } } @@ -156,9 +171,17 @@ try { } if ($js_output_file) { - $js_minifier->minify($js_output_file); + if (in_array('gzip', $cli['flags'])) { + $js_minifier->gzip($js_output_file); + } else { + $js_minifier->minify($js_output_file); + } } else { - echo $js_minifier->minify(); + if (in_array('gzip', $cli['flags'])) { + echo $js_minifier->gzip(); + } else { + echo $js_minifier->minify(); + } } } } catch (Exception $e) { From 284e25bf37622fb1e8bfe7fce7d96477bcea69a1 Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Thu, 30 Dec 2021 15:42:13 -0600 Subject: [PATCH 3/7] Move gzip check logic to variable --- bin/minify | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bin/minify b/bin/minify index 5ae2226f..661eda91 100755 --- a/bin/minify +++ b/bin/minify @@ -89,6 +89,8 @@ $cli = parse_argv( ) ); +$gzip = in_array('gzip', $cli['flags']); + // Check if script run in a CLI environment if ('cli' !== php_sapi_name()) { fwrite(STDERR, $cli['command'] . ' must be run in the command line' . PHP_EOL); @@ -149,13 +151,13 @@ try { } if ($css_output_file) { - if (in_array('gzip', $cli['flags'])) { + if ($gzip) { $css_minifier->gzip($css_output_file); } else { $css_minifier->minify($css_output_file); } } else { - if (in_array('gzip', $cli['flags'])) { + if ($gzip) { echo $css_minifier->gzip(); } else { echo $css_minifier->minify(); @@ -171,13 +173,13 @@ try { } if ($js_output_file) { - if (in_array('gzip', $cli['flags'])) { + if ($gzip) { $js_minifier->gzip($js_output_file); } else { $js_minifier->minify($js_output_file); } } else { - if (in_array('gzip', $cli['flags'])) { + if ($gzip) { echo $js_minifier->gzip(); } else { echo $js_minifier->minify(); From 9f272f8ec9bdb4f91ceca8e834b9e9761795cbcb Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Thu, 30 Dec 2021 15:45:33 -0600 Subject: [PATCH 4/7] Add max-import-size option to CLI --- README.md | 1 + bin/minify | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ba5917cb..35cfdefe 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Multiple source files can be passed, both CSS and JS. Define an output file for #### Options * `--gzip`/`-g` - `gzencode()`s the minified content + * `--max-import-size`/`-m` - The maximum import size (in kB) for CSS * `--output`/`-o` - The file path to write the minified content to diff --git a/bin/minify b/bin/minify index 661eda91..1bf41e2f 100755 --- a/bin/minify +++ b/bin/minify @@ -82,6 +82,7 @@ $cli = parse_argv( $argv, array( 'g' => 'gzip', + 'm' => 'max-import-size', 'o' => 'output' ), array( @@ -145,7 +146,11 @@ if (isset($cli['options']['output'])) { try { if (!empty($css_files)) { $css_minifier = new Minify\CSS(); - + + if (isset($cli['options']['max-import-size'])) { + $css_minifier->setMaxImportSize($cli['options']['max-import-size']); + } + foreach($css_files as $css_file) { $css_minifier->add($css_file); } From 4f49a2941cb0d7c37a48919937b434ae45fb4223 Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Thu, 30 Dec 2021 16:01:58 -0600 Subject: [PATCH 5/7] Add import-ext option to CLI tool --- README.md | 1 + bin/minify | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 35cfdefe..88430c13 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ Multiple source files can be passed, both CSS and JS. Define an output file for #### Options + * `--import-ext`/`-e` - Defines an extension that will be imported in CSS (ex. `-e "gif|data:image/gif -e "png|data:image/png"`) * `--gzip`/`-g` - `gzencode()`s the minified content * `--max-import-size`/`-m` - The maximum import size (in kB) for CSS * `--output`/`-o` - The file path to write the minified content to diff --git a/bin/minify b/bin/minify index 1bf41e2f..ff0254e7 100755 --- a/bin/minify +++ b/bin/minify @@ -79,19 +79,18 @@ if (!isset($_SERVER['argv']) && !isset($argv)) { // Parse CLI arguments $cli = parse_argv( - $argv, - array( - 'g' => 'gzip', - 'm' => 'max-import-size', - 'o' => 'output' - ), - array( - 'gzip' - ) + $argv, + array( + 'e' => 'import-ext', + 'g' => 'gzip', + 'm' => 'max-import-size', + 'o' => 'output' + ), + array( + 'gzip' + ) ); -$gzip = in_array('gzip', $cli['flags']); - // Check if script run in a CLI environment if ('cli' !== php_sapi_name()) { fwrite(STDERR, $cli['command'] . ' must be run in the command line' . PHP_EOL); @@ -112,6 +111,22 @@ foreach($cli['arguments'] as $source_file) { } } +$gzip = in_array('gzip', $cli['flags']); + +// Get CSS Import Extensions if any +$import_exts = null; +if (isset($cli['options']['import-ext'])) { + $import_exts = array(); + + foreach((array) $cli['options']['import-ext'] as $ext) { + $ext_split = explode('|', $ext); + + if (count($ext_split) === 2) { + $import_exts[$ext_split[0]] = $ext_split[1]; + } + } +} + // Get CSS files $css_files = array_filter($cli['arguments'], function($arg) { return substr($arg, -4) === '.css'; @@ -151,6 +166,10 @@ try { $css_minifier->setMaxImportSize($cli['options']['max-import-size']); } + if (isset($import_exts)) { + $css_minifier->setImportExtensions($import_exts); + } + foreach($css_files as $css_file) { $css_minifier->add($css_file); } From afc86b2c69b6bc9b75eae2bc2ec9b3318c26f907 Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Thu, 30 Dec 2021 22:01:57 -0600 Subject: [PATCH 6/7] Add support for wildcard output paths in the CLI tool --- README.md | 2 + bin/minify | 126 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 88430c13..4f7f1856 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,8 @@ vendor/bin/minify /path/to/source/*.css -o /path/to/minified/css/file.css /path/ Multiple source files can be passed, both CSS and JS. Define an output file for each file type with the `--output` or `-o` option. If an output file is not defined, the minified contents will be sent to `STDOUT`. +You can also have each input file generate it's own minified file rather than having them be combined into a single file by defining an output path with an asterisk (`*`) that will be replaced with the input filename (ex. `-o "/path/to/minified/js/*.min.js"`), however you'll want to make sure that you wrap the path in quotes so that your terminal doesn't try to parse the path itself. + #### Options * `--import-ext`/`-e` - Defines an extension that will be imported in CSS (ex. `-e "gif|data:image/gif -e "png|data:image/png"`) diff --git a/bin/minify b/bin/minify index ff0254e7..4aea6ef6 100755 --- a/bin/minify +++ b/bin/minify @@ -129,84 +129,120 @@ if (isset($cli['options']['import-ext'])) { // Get CSS files $css_files = array_filter($cli['arguments'], function($arg) { - return substr($arg, -4) === '.css'; + return strtolower(substr($arg, -4)) === '.css'; }); // Get JS files $js_files = array_filter($cli['arguments'], function($arg) { - return substr($arg, -3) === '.js'; + return strtolower(substr($arg, -3)) === '.js'; }); // Get output files, if any $css_output_file = null; $js_output_file = null; if (isset($cli['options']['output'])) { - $css_output_files = array_values(array_filter((array) $cli['options']['output'], function($out) { - return substr($out, -4) === '.css'; - })); + if (!empty($css_files)) { + $css_output_files = array_values(array_filter((array) $cli['options']['output'], function($out) { + return strtolower(substr($out, -4)) === '.css'; + })); - if (!empty($css_output_files)) { - $css_output_file = $css_output_files[0]; + if (!empty($css_output_files)) { + $css_output_file = end($css_output_files); + } } - - $js_output_files = array_values(array_filter((array) $cli['options']['output'], function($out) { - return substr($out, -3) === '.js'; - })); - - if (!empty($js_output_files)) { - $js_output_file = $js_output_files[0]; + + if (!empty($js_files)) { + $js_output_files = array_values(array_filter((array) $cli['options']['output'], function($out) { + return strtolower(substr($out, -3)) === '.js'; + })); + + if (!empty($js_output_files)) { + $js_output_file = end($js_output_files); + } } } try { if (!empty($css_files)) { - $css_minifier = new Minify\CSS(); + $css_compile_count = 1; + $css_wildcard_output = false; - if (isset($cli['options']['max-import-size'])) { - $css_minifier->setMaxImportSize($cli['options']['max-import-size']); + if ($css_output_file && strpos($css_output_file, '*') !== false) { + $css_compile_count = count($css_files); + $css_wildcard_output = $css_output_file; } - if (isset($import_exts)) { - $css_minifier->setImportExtensions($import_exts); - } + for ($x = 0; $x <= $css_compile_count - 1; $x++) { + $css_minifier = new Minify\CSS(); - foreach($css_files as $css_file) { - $css_minifier->add($css_file); - } - - if ($css_output_file) { - if ($gzip) { - $css_minifier->gzip($css_output_file); + if (isset($cli['options']['max-import-size'])) { + $css_minifier->setMaxImportSize($cli['options']['max-import-size']); + } + + if (isset($import_exts)) { + $css_minifier->setImportExtensions($import_exts); + } + + if ($css_wildcard_output) { + $css_minifier->add($css_files[$x]); + $css_input_info = pathinfo($css_files[$x]); + $css_output_file = str_replace('*', $css_input_info['filename'], $css_wildcard_output); } else { - $css_minifier->minify($css_output_file); + foreach($css_files as $css_file) { + $css_minifier->add($css_file); + } } - } else { - if ($gzip) { - echo $css_minifier->gzip(); + + if ($css_output_file) { + if ($gzip) { + $css_minifier->gzip($css_output_file); + } else { + $css_minifier->minify($css_output_file); + } } else { - echo $css_minifier->minify(); + if ($gzip) { + echo $css_minifier->gzip(); + } else { + echo $css_minifier->minify(); + } } } } if (!empty($js_files)) { - $js_minifier = new Minify\JS(); - - foreach($js_files as $js_file) { - $js_minifier->add($js_file); + $js_compile_count = 1; + $js_wildcard_output = false; + + if ($js_output_file && strpos($js_output_file, '*') !== false) { + $js_compile_count = count($js_files); + $js_wildcard_output = $js_output_file; } - - if ($js_output_file) { - if ($gzip) { - $js_minifier->gzip($js_output_file); + + for ($x = 0; $x <= $js_compile_count - 1; $x++) { + $js_minifier = new Minify\JS(); + + if ($js_wildcard_output) { + $js_minifier->add($js_files[$x]); + $js_input_info = pathinfo($js_files[$x]); + $js_output_file = str_replace('*', $js_input_info['filename'], $js_wildcard_output); } else { - $js_minifier->minify($js_output_file); + foreach($js_files as $js_file) { + $js_minifier->add($js_file); + } } - } else { - if ($gzip) { - echo $js_minifier->gzip(); + + if ($js_output_file) { + if ($gzip) { + $js_minifier->gzip($js_output_file); + } else { + $js_minifier->minify($js_output_file); + } } else { - echo $js_minifier->minify(); + if ($gzip) { + echo $js_minifier->gzip(); + } else { + echo $js_minifier->minify(); + } } } } From b91c36eb8b554e76943f0cfb811cc6920df98891 Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Thu, 30 Dec 2021 22:29:27 -0600 Subject: [PATCH 7/7] Add help option to CLI tool --- README.md | 3 ++- bin/minify | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f7f1856..6b026f73 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,11 @@ You can also have each input file generate it's own minified file rather than ha #### Options - * `--import-ext`/`-e` - Defines an extension that will be imported in CSS (ex. `-e "gif|data:image/gif -e "png|data:image/png"`) + * `--import-ext`/`-e` - Defines an extension that will be imported in CSS (ex. `-e "gif|data:image/gif" -e "png|data:image/png"`) * `--gzip`/`-g` - `gzencode()`s the minified content * `--max-import-size`/`-m` - The maximum import size (in kB) for CSS * `--output`/`-o` - The file path to write the minified content to + * `--help`/`-h` - Displays information about the CLI tool (you can also pass `help` as the first argument) ## Methods diff --git a/bin/minify b/bin/minify index 4aea6ef6..53efdd6b 100755 --- a/bin/minify +++ b/bin/minify @@ -83,11 +83,13 @@ $cli = parse_argv( array( 'e' => 'import-ext', 'g' => 'gzip', + 'h' => 'help', 'm' => 'max-import-size', 'o' => 'output' ), array( - 'gzip' + 'gzip', + 'help' ) ); @@ -103,6 +105,31 @@ if (empty($cli['arguments'])) { exit(1); } +// Display helpful information about the CLI tool if the first argument is 'help' or the help flag is used +if (strtolower($cli['arguments'][0]) === 'help' || in_array('help', $cli['flags'])) { + echo " +Minify +https://github.com/matthiasmullie/minify + +Removes whitespace, strips comments, combines files and optimizes/shortens a few common programming patterns. + +Usage: + minify [additional_input_files...] + +Options: + --import-ext <1>, -e <1> Defines an extension that will be imported in CSS (ex. `-e \"gif|data:image/gif\" -e \"png|data:image/png\"`) + + --gzip <1>, -g <1> gzencode()'s the minified content + + --max-import-size <1>, -m <1> The maximum import size (in kB) for CSS + + --output <1>, -o <1> The file path to write the minified content to + +"; + + exit; +} + // Check if source files exist foreach($cli['arguments'] as $source_file) { if (!file_exists($source_file)) {