-
-
Save Rodrigo54/93169db48194d470188f to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* ----------------------------------------------------------------------------------------- | |
* Based on `https://github.com/mecha-cms/mecha-cms/blob/master/system/kernel/converter.php` | |
* ----------------------------------------------------------------------------------------- | |
*/ | |
// HTML Minifier | |
function minify_html($input) { | |
if(trim($input) === "") return $input; | |
// Remove extra white-space(s) between HTML attribute(s) | |
$input = 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", "", $input)); | |
// Minify inline CSS declaration(s) | |
if(strpos($input, ' style=') !== false) { | |
$input = preg_replace_callback('#<([^<]+?)\s+style=([\'"])(.*?)\2(?=[\/\s>])#s', function($matches) { | |
return '<' . $matches[1] . ' style=' . $matches[2] . minify_css($matches[3]) . $matches[2]; | |
}, $input); | |
} | |
if(strpos($input, '</style>') !== false) { | |
$input = preg_replace_callback('#<style(.*?)>(.*?)</style>#is', function($matches) { | |
return '<style' . $matches[1] .'>'. minify_css($matches[2]) . '</style>'; | |
}, $input); | |
} | |
if(strpos($input, '</script>') !== false) { | |
$input = preg_replace_callback('#<script(.*?)>(.*?)</script>#is', function($matches) { | |
return '<script' . $matches[1] .'>'. minify_js($matches[2]) . '</script>'; | |
}, $input); | |
} | |
return preg_replace( | |
array( | |
// t = text | |
// o = tag open | |
// c = tag close | |
// Keep important white-space(s) after self-closing HTML tag(s) | |
'#<(img|input)(>| .*?>)#s', | |
// Remove a line break and two or more white-space(s) between tag(s) | |
'#(<!--.*?-->)|(>)(?:\n*|\s{2,})(<)|^\s*|\s*$#s', | |
'#(<!--.*?-->)|(?<!\>)\s+(<\/.*?>)|(<[^\/]*?>)\s+(?!\<)#s', // t+c || o+t | |
'#(<!--.*?-->)|(<[^\/]*?>)\s+(<[^\/]*?>)|(<\/.*?>)\s+(<\/.*?>)#s', // o+o || c+c | |
'#(<!--.*?-->)|(<\/.*?>)\s+(\s)(?!\<)|(?<!\>)\s+(\s)(<[^\/]*?\/?>)|(<[^\/]*?\/?>)\s+(\s)(?!\<)#s', // c+t || t+o || o+t -- separated by long white-space(s) | |
'#(<!--.*?-->)|(<[^\/]*?>)\s+(<\/.*?>)#s', // empty tag | |
'#<(img|input)(>| .*?>)<\/\1>#s', // reset previous fix | |
'#( ) (?![<\s])#', // clean up ... | |
'#(?<=\>)( )(?=\<)#', // --ibid | |
// Remove HTML comment(s) except IE comment(s) | |
'#\s*<!--(?!\[if\s).*?-->\s*|(?<!\>)\n+(?=\<[^!])#s' | |
), | |
array( | |
'<$1$2</$1>', | |
'$1$2$3', | |
'$1$2$3', | |
'$1$2$3$4$5', | |
'$1$2$3$4$5$6$7', | |
'$1$2$3', | |
'<$1$2', | |
'$1 ', | |
'$1', | |
"" | |
), | |
$input); | |
} | |
// CSS Minifier => http://ideone.com/Q5USEF + improvement(s) | |
function minify_css($input) { | |
if(trim($input) === "") return $input; | |
return preg_replace( | |
array( | |
// Remove comment(s) | |
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')|\/\*(?!\!)(?>.*?\*\/)|^\s*|\s*$#s', | |
// 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', | |
// Replace `0(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)` with `0` | |
'#(?<=[\s:])(0)(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)#si', | |
// Replace `:0 0 0 0` with `:0` | |
'#:(0\s+0|0\s+0\s+0\s+0)(?=[;\}]|\!important)#i', | |
// Replace `background-position:0` with `background-position:0 0` | |
'#(background-position):0(?=[;\}])#si', | |
// Replace `0.6` with `.6`, but only when preceded by `:`, `,`, `-` or a white-space | |
'#(?<=[\s:,\-])0+\.(\d+)#s', | |
// Minify string value | |
'#(\/\*(?>.*?\*\/))|(?<!content\:)([\'"])([a-z_][a-z0-9\-_]*?)\2(?=[\s\{\}\];,])#si', | |
'#(\/\*(?>.*?\*\/))|(\burl\()([\'"])([^\s]+?)\3(\))#si', | |
// Minify HEX color code | |
'#(?<=[\s:,\-]\#)([a-f0-6]+)\1([a-f0-6]+)\2([a-f0-6]+)\3#i', | |
// Replace `(border|outline):none` with `(border|outline):0` | |
'#(?<=[\{;])(border|outline):none(?=[;\}\!])#', | |
// Remove empty selector(s) | |
'#(\/\*(?>.*?\*\/))|(^|[\{\}])(?:[^\s\{\}]+)\{\}#s' | |
), | |
array( | |
'$1', | |
'$1$2$3$4$5$6$7', | |
'$1', | |
':0', | |
'$1:0 0', | |
'.$1', | |
'$1$3', | |
'$1$2$4$5', | |
'$1$2$3', | |
'$1:0', | |
'$1$2' | |
), | |
$input); | |
} | |
// JavaScript Minifier | |
function minify_js($input) { | |
if(trim($input) === "") return $input; | |
return preg_replace( | |
array( | |
// Remove comment(s) | |
'#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*\/\*(?!\!|@cc_on)(?>[\s\S]*?\*\/)\s*|\s*(?<![\:\=])\/\/.*(?=[\n\r]|$)|^\s*|\s*$#', | |
// Remove white-space(s) outside the string and regex | |
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/)|\/(?!\/)[^\n\r]*?\/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#s', | |
// Remove the last semicolon | |
'#;+\}#', | |
// Minify object attribute(s) except JSON attribute(s). From `{'foo':'bar'}` to `{foo:'bar'}` | |
'#([\{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=\:)#i', | |
// --ibid. From `foo['bar']` to `foo.bar` | |
'#([a-z0-9_\)\]])\[([\'"])([a-z_][a-z0-9_]*)\2\]#i' | |
), | |
array( | |
'$1', | |
'$1$2', | |
'}', | |
'$1$3', | |
'$1.$3' | |
), | |
$input); | |
} |
Hey guys, this removes spaces in css that are inside a
calc()
which leads to it becoming an invalid property value, does anyone know the fix?
maybe is too late, but just FYI ive fixed it on a old project i made TriForceX/BootstrapExtended#14
Ran into a bug using this function with exceptionally large files (like 1 MB+ worth of HTML to minify). Specifically, above a certain string size, minify_html seems to return an empty string (or some other false-y value).
Added a "ghetto hack" as shown below. HTML will not be minified, but will at least return the original HTML.
$original_input = $input;
/* The rest of the function */
if (!$input)
return $original_input;
return $input;
One problem, it removes whitespace in CSS calc() for example
font-size: calc(36px + (80 - 36) * (100vw - 320px) / (1366 - 320));
Becomes:
font-size: calc(36px+(80-36) * (100vw-320px) / (1366-320));
Which is invalid.
Fixed problem in whitespace in CSS calc()
thanks @jcmarchi and @TriForceX for solution
css replace 0% It will cause crash keyframes uses ( 0% ) ...
css replace 0% It will cause crash keyframes uses ( 0% ) ...
Hi Rodrigo, any lucky looking into this one? keyframes are increasingly getting more important in nowadays CSS implementations and it can surely start being a problem in many cases.
css replace 0% It will cause crash keyframes uses ( 0% ) ...
Though I don't do css much, I think \d%
in keyframe rules is always followed by {
. Hence this pattern would work: (?<=[\s:])(0)(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)(?!\s*\{)
.
One problem,
var loadPage = function(){
// Content
}
var loadPage = function(){
// Content
}
When compressing an error.
Here is correct.
var loadPage = function(){
// Content
};
var loadPage = function(){
// Content
};
How to fix this.
Thank!
These are great, thanks! Like others, I removed the 0 replacement line. Thanks for much for sharing.
Thank you so much
could you guys explain me about Keep important white-space(s) after self-closing HTML tag(s) '#<(img|input)(>| .*?>)#s',
and '#<(img|input)(>| .*?>)<\/\1>#s'
an example would be great 😄
Thanks <3