Last active
August 19, 2021 02:20
-
-
Save ozws/a24544a3df576361d389fdac861aa280 to your computer and use it in GitHub Desktop.
php class Minify
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace YourNamespace; | |
class Minify { | |
/* | |
Use: | |
Minify::html( string ) | |
Minify::css( string ) | |
Minify::js( string ) | |
*/ | |
/** | |
* Constructor. | |
* | |
*/ | |
public function __construct() {} | |
public static function html( $html ) { | |
if ( trim( $html ) === '' ) | |
return $html; | |
// Remove extra white-space(s) between HTML attribute(s) | |
$html = preg_replace_callback('#<([^\/\s<>!]+)(?:\s+([^<>]*?)\s*|\s*)(\/?)>#s', function( $matches ) { | |
return '<' . $matches[1] . preg_replace('#([^\s=]+)(\=([\'"]?)(.*?)\3)?(\s+|$)#s', ' $1$2', $matches[2]) . $matches[3] . '>'; | |
}, str_replace( "\r", "", $html ) ); | |
// Minify inline CSS declaration(s) | |
if ( strpos( $html, ' style=' ) !== false ) { | |
$html = preg_replace_callback('#<([^<]+?)\s+style=([\'"])(.*?)\2(?=[\/\s>])#s', function( $matches ) { | |
return '<' . $matches[1] . ' style=' . $matches[2] . Minify::css($matches[3]) . $matches[2]; | |
}, $html); | |
} | |
// Handle style tags | |
if ( strpos( $html, '</style>' ) !== false ) { | |
$html = preg_replace_callback('#<style(.*?)>(.*?)</style>#is', function( $matches ) { | |
return '<style' . $matches[1] .'>'. Minify::css($matches[2]) . '</style>'; | |
}, $html); | |
} | |
// Handle script tags | |
if ( strpos( $html, '</script>' ) !== false ) { | |
$html = preg_replace_callback('#<script(.*?)>(.*?)</script>#is', function( $matches ) { | |
return '<script' . $matches[1] .'>'. Minify::js($matches[2]) . '</script>'; | |
}, $html); | |
} | |
$html = preg_replace( | |
[ | |
// t = text | |
// o = tag open | |
// c = tag close | |
// 1 - Keep important white-space(s) after self-closing HTML tag(s) | |
'#<(img|input)(>| .*?>)#s', | |
// 2 - Remove a line break and two or more white-space(s) between tag(s) | |
'#(<!--.*?-->)|(>)(?:\n*|\s{2,})(<)|^\s*|\s*$#s', | |
// 3 - t+c || o+t | |
'#(<!--.*?-->)|(?<!\>)\s+(<\/.*?>)|(<[^\/]*?>)\s+(?!\<)#s', | |
// 4 - o+o || c+c | |
'#(<!--.*?-->)|(<[^\/]*?>)\s+(<[^\/]*?>)|(<\/.*?>)\s+(<\/.*?>)#s', | |
// 5 - c+t || t+o || o+t -- separated by long white-space(s) | |
'#(<!--.*?-->)|(<\/.*?>)\s+(\s)(?!\<)|(?<!\>)\s+(\s)(<[^\/]*?\/?>)|(<[^\/]*?\/?>)\s+(\s)(?!\<)#s', | |
// 6 - empty tag | |
'#(<!--.*?-->)|(<[^\/]*?>)\s+(<\/.*?>)#s', | |
// 7 - reset previous fix | |
'#<(img|input)(>| .*?>)<\/\1>#s', | |
// 8 - clean up ... | |
'#( ) (?![<\s])#', | |
// 9 - --ibid | |
'#(?<=\>)( )(?=\<)#', | |
// 10 - Remove HTML comment(s) except IE comment(s) | |
'#\s*<!--(?!\[if\s).*?-->\s*|(?<!\>)\n+(?=\<[^!])#s' | |
], | |
[ | |
'<$1$2</$1>', // 1 | |
'$1$2$3', // 2 | |
'$1$2$3', // 3 | |
'$1$2$3$4$5', // 4 | |
'$1$2$3$4$5$6$7', // 5 | |
'$1$2$3', // 6 | |
'<$1$2', // 7 | |
'$1 ', // 8 | |
'$1', // 9 | |
"", // 10 | |
], | |
$html | |
); | |
return $html; | |
} | |
public static function css( $css ) { | |
if ( trim( $css ) === '' ) | |
return $css; | |
$css = preg_replace( | |
[ | |
// 1 - Remove comment(s) | |
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')|\/\*(?!\!)(?>.*?\*\/)|^\s*|\s*$#s', | |
// 2 - Remove unused white-space(s) | |
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/))|\s*+;\s*+(})\s*+|\s*+([*$~^|]?+=|[{};,>~]|\s(?![0-9\.])|!important\b)\s*+|([[(:])\s++|\s++([])])|\s++(:)\s*+(?!(?>[^{}"\']++|"(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')*+{)|^\s++|\s++\z|(\s)\s+#si', | |
// 3 - Replace `0(cm|rem|em|ex|in|mm|pc|pt|px|vh|vw|%)` with `0` | |
'#(?<=[\s:])(0)(cm|rem|em|ex|in|mm|pc|pt|px|vh|vw|%)#si', | |
// 4 - Replace `:0 0 0 0` with `:0` | |
'#:(0\s+0|0\s+0\s+0\s+0)(?=[;\}]|\!important)#i', | |
// 5 - Replace `background-position:0` with `background-position:0 0` | |
'#(background-position):0(?=[;\}])#si', | |
// 6 - Replace `0.6` with `.6`, but only when preceded by `:`, `,`, `-` or a white-space | |
'#(?<=[\s:,\-])0+\.(\d+)#s', | |
// 7/8 - Minify string value | |
'#(\/\*(?>.*?\*\/))|(?<!content\:)([\'"])([a-z_][a-z0-9\-_]*?)\2(?=[\s\{\}\];,])#si', | |
'#(\/\*(?>.*?\*\/))|(\burl\()([\'"])([^\s]+?)\3(\))#si', | |
// 9 - Minify HEX color code | |
'#(?<=[\s:,\-]\#)([a-f0-6]+)\1([a-f0-6]+)\2([a-f0-6]+)\3#i', | |
// 10 - Replace `(border|outline):none` with `(border|outline):0` | |
'#(?<=[\{;])(border|outline):none(?=[;\}\!])#', | |
// 11 - Remove empty selector(s) | |
'#(\/\*(?>.*?\*\/))|(^|[\{\}])(?:[^\s\{\}]+)\{\}#s', | |
], | |
[ | |
'$1', // 1 | |
'$1$2$3$4$5$6$7', // 2 | |
'$1', // 3 | |
':0', // 4 | |
'$1:0 0', // 5 | |
'.$1', // 6 | |
'$1$3', // 7 | |
'$1$2$4$5', // 8 | |
'$1$2$3', // 9 | |
'$1:0', // 10 | |
'$1$2', // 11 | |
], | |
$css | |
); | |
return trim( $css ); | |
} | |
public static function js( $js ) { | |
if ( trim( $js ) === '' ) | |
return $js; | |
$js = preg_replace( | |
[ | |
// 1 - Remove comment(s) | |
'#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*\/\*(?!\!|@cc_on)(?>[\s\S]*?\*\/)\s*|\s*(?<![\:\=])\/\/.*(?=[\n\r]|$)|^\s*|\s*$#', | |
// 2 - Remove white-space(s) outside the string and regex | |
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/)|\/(?!\/)[^\n\r]*?\/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#s', | |
// 3 - Remove the last semicolon | |
'#;+\}#', | |
// 4 - Minify object attribute(s) except JSON attribute(s). From `{'foo':'bar'}` to `{foo:'bar'}` | |
'#([\{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=\:)#i', | |
// 5 - --ibid. From `foo['bar']` to `foo.bar` | |
'#([a-z0-9_\)\]])\[([\'"])([a-z_][a-z0-9_]*)\2\]#i', | |
], | |
[ | |
'$1', // 1 | |
'$1$2', // 2 | |
'}', // 3 | |
'$1$3', // 4 | |
'$1.$3', // 5 | |
], | |
$js | |
); | |
return $js; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment