validar strip_tags remove regulares preg_match online from expresiones php css regex pcre minify

strip_tags - preg_match php



¿Reducir/comprimir CSS con expresiones regulares? (4)

En PHP, ¿puede comprimir / minimizar CSS con expresiones regulares (PCRE)?

(Como teórico en expresiones regulares. Estoy seguro de que hay bibliotecas que lo hacen bien).

Nota de fondo: después de pasar horas escribiendo una respuesta a una pregunta eliminada (media mierda) , pensé que publicaría una parte de la pregunta subyacente y la respondería yo misma. Espero que esté bien.


Simple regex CSS minifier / compresor

(Ok, puede que no sea demasiado simple, pero bastante sencillo).

Requerimientos

Esta respuesta asume que los requisitos son:

  • Eliminar comentarios
  • Reemplace las combinaciones de espacios en blanco más de 1 espacio con un solo espacio
  • Elimine todos los espacios en blanco alrededor de los metacaracteres: { , } ; ~ > , ~ , + , -
  • Eliminar espacios alrededor !important
  • Eliminar espacios alrededor de : excepto en los selectores (donde tiene que mantener un espacio delante de él)
  • Eliminar espacios alrededor de operadores como $=
  • Eliminar todos los espacios a la derecha de ( / [ e izquierda de ) / ]
  • Eliminar todos los espacios al principio y al final de la cadena
  • Quite el último ; en un bloque
  • No cambies nada en las cuerdas.
  • No tiene que trabajar en CSS inválido

Tenga en cuenta que los requisitos aquí no incluyen la conversión de las propiedades CSS a versiones más cortas (como el uso de propiedades abreviadas en lugar de varias propiedades de longitud completa, eliminando las comillas donde no sea necesario). Esto es algo que regex no podría resolver en general.

Solución

Es más fácil resolver esto en dos pasos: primero elimine los comentarios, luego todo lo demás.

Debería ser posible hacerlo en una sola pasada, pero luego debe reemplazar todos /s con una expresión que coincida con espacios y comentarios (entre otras modificaciones).

La primera expresión de pase para eliminar comentarios:

(?xs) # quotes ( "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' ) | # comments //* (?> .*? /*/ )

Reemplazar con $1 .

Y para eliminar todo lo demás puedes usar:

(?six) # quotes ( "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' ) | # ; before } (and the spaces after it while we''re here) /s*+ ; /s*+ ( } ) /s*+ | # all spaces around meta chars/operators /s*+ ( [*$~^|]?+= | [{};,>~+-] | !important/b ) /s*+ | # spaces right of ( [ : ( [[(:] ) /s++ | # spaces left of ) ] /s++ ( [])] ) | # spaces left (and right) of : /s++ ( : ) /s*+ # but not in selectors: not followed by a { (?! (?> [^{}"'']++ | "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' )*+ { ) | # spaces at beginning/end of string ^ /s++ | /s++ /z | # double spaces to single (/s)/s+

Reemplazado con $1$2$3$4$5$6$7 .

La selección del selector para eliminar espacios antes : (el lookahead negativo) puede ralentizar esto en comparación con los analizadores adecuados. Los analizadores ya saben si están en un selector o no, y no tienen que hacer búsquedas adicionales para verificarlo.

Ejemplo de implementación en PHP

function minify_css($str){ # remove comments first (simplifies the other regex) $re1 = <<<''EOS'' (?sx) # quotes ( "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' ) | # comments //* (?> .*? /*/ ) EOS; $re2 = <<<''EOS'' (?six) # quotes ( "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' ) | # ; before } (and the spaces after it while we''re here) /s*+ ; /s*+ ( } ) /s*+ | # all spaces around meta chars/operators /s*+ ( [*$~^|]?+= | [{};,>~+-] | !important/b ) /s*+ | # spaces right of ( [ : ( [[(:] ) /s++ | # spaces left of ) ] /s++ ( [])] ) | # spaces left (and right) of : /s++ ( : ) /s*+ # but not in selectors: not followed by a { (?! (?> [^{}"'']++ | "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' )*+ { ) | # spaces at beginning/end of string ^ /s++ | /s++ /z | # double spaces to single (/s)/s+ EOS; $str = preg_replace("%$re1%", ''$1'', $str); return preg_replace("%$re2%", ''$1$2$3$4$5$6$7'', $str); }

Examen rápido

Se puede encontrar en ideone.com :

$in = <<<''EOS'' p * i , html /* remove spaces */ /* " comments have no escapes /*/ body/* keep */ /* space */p, p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i , div::after { /* comment */ background : url( " /* string */ " ) blue !important ; content : " escapes /" allowed //" ; width: calc( 100% - 3em + 5px ) ; margin-top : 0; margin-bottom : 0; margin-left : 10px; margin-right : 10px; } EOS; $out = minify_css($in); echo "input:/n"; var_dump($in); echo "/n/n"; echo "output:/n"; var_dump($out);

Salida:

input: string(435) " p * i , html /* remove spaces */ /* " comments have no escapes /*/ body/* keep */ /* space */p, p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i , div::after { /* comment */ background : url( " /* string */ " ) blue !important ; content : " escapes /" allowed //" ; width: calc( 100% - 3em + 5px ) ; margin-top : 0; margin-bottom : 0; margin-left : 10px; margin-right : 10px; } " output: string(251) "p * i,html body p,p [remove~=" spaces "] :nth-child(3+2n)>b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes /" allowed //";width:calc(100%-3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px}"

Comparado

cssminifier.com

Resultados de cssminifier.com para la misma entrada que la prueba anterior:

p * i,html /*/*/body/**/p,p [remove ~= " spaces "] :nth-child(3+2n)>b span i,div::after{background:url(" /* string */ ") blue;content:" escapes /" allowed //";width:calc(100% - 3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px}

Longitud 263 bytes. 12 bytes más largos que la salida del minificador de expresiones regulares anterior.

cssminifier.com tiene algunas desventajas en comparación con este cssminifier.com regulares:

  • Deja parte de los comentarios. (Puede haber una razón para esto. Tal vez algunos hacks CSS).
  • No elimina espacios alrededor de los operadores en algunas expresiones.

CSSTidy

Salida de CSSTidy 1.3 (a través de codebeautifier.com ) con el preajuste de nivel de compresión más alto:

p * i,html /* remove spaces */ /* " comments have no escapes /*/ body/* keep */ /* space */p,p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes /" allowed //";width:calc(100%-3em+5px);margin:0 10px;}

Longitud 286 bytes. 35 bytes más largos que la salida del minificador de expresiones regulares.

CSSTidy no elimina comentarios o espacios en algunos selectores. Pero se reduce a las propiedades de taquigrafía. Este último probablemente debería ayudar a comprimir el CSS normal mucho más.

Comparación lado a lado

Salida reducida de los diferentes minificadores para la misma entrada que en el ejemplo anterior. (Saltos de línea sobrantes reemplazados con espacios).

this answern (251): p * i,html body p,p [remove~=" spaces "] :nth-child(3+2n)>b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes /" allowed //";width:calc(100%-3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px} cssminifier.com (263): p * i,html /*/*/body/**/p,p [remove ~= " spaces "] :nth-child(3+2n)>b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes /" allowed //";width:calc(100% - 3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px} CSSTidy 1.3 (286): p * i,html /* remove spaces */ /* " comments have no escapes /*/ body/* keep */ /* space */p,p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes /" allowed //";width:calc(100%-3em+5px);margin:0 10px;}

Para CSS normal, CSSTidy es probablemente mejor, ya que se convierte en propiedades abreviadas.

Supongo que hay otros minificadores (como el compresor YUI) que deberían ser mejores y dar un resultado más corto que este minificador de expresiones regulares.


Aquí hay una fuente compacta de cómo lo hago. Con la compresión. Y no tiene que preocuparse, si cambia algo en la fuente.

De hecho, ''// comentarios'' no están permitidos en css.

ob_start(''ob_handler''); if(!file_exists(''style/style-min.css) or filemtime(''style/style.css'') > filemtime(''style/style-min.css'')){ $css=file_get_contents(''style/style.css''); //you need to escape some more charactes if pattern is an external string. $from=array(''@//s*///*.*//*///s*@sU'', ''///s{2,}/''); $to= array('''' , '' ''); $css=preg_replace($from,$to,$css); $css=preg_replace(''@/s*([/:;,."/'{}()])/s*@'',"$1",$css); $css=preg_replace(''@;}@'',''}'',$css); header(''Content-type: text/css''); echo $css; file_put_contents(''style/style-min.css'',$css); //etag- modified- cache-control- header } else{ //exit if not modified? //etag- modified- cache-control- header header(''Content-type: text/css''); readfile(''style/style-min.css''); } ob_end_flush();

PD: ¿Quién me dio el menos antes de que esté listo para escribir? QTax- Por poco tiempo olvidé escapar de las barras invertidas en la matriz $ fom. PSS. Solo la nueva versión de PHP comprueba el parámetro ''U'', que hace que una expresión regular no sea un problema.


Aquí hay una versión ligeramente modificada de la respuesta de @ Qtax que resuelve los problemas con calc() gracias a un regex alternativo de la biblioteca Minify de @ matthiasmullie''s .

function minify_css( $string = '''' ) { $comments = <<<''EOS'' (?sx) # don''t change anything inside of quotes ( "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' ) | # comments //* (?> .*? /*/ ) EOS; $everything_else = <<<''EOS'' (?six) # don''t change anything inside of quotes ( "(?:[^"//]++|//.)*+" | ''(?:[^''//]++|//.)*+'' ) | # spaces before and after ; and } /s*+ ; /s*+ ( } ) /s*+ | # all spaces around meta chars/operators (excluding + and -) /s*+ ( [*$~^|]?+= | [{};,>~] | !important/b ) /s*+ | # all spaces around + and - (in selectors only!) /s*([+-])/s*(?=[^}]*{) | # spaces right of ( [ : ( [[(:] ) /s++ | # spaces left of ) ] /s++ ( [])] ) | # spaces left (and right) of : (but not in selectors)! /s+(:)(?![^/}]*/{) | # spaces at beginning/end of string ^ /s++ | /s++ /z | # double spaces to single (/s)/s+ EOS; $search_patterns = array( "%{$comments}%", "%{$everything_else}%" ); $replace_patterns = array( ''$1'', ''$1$2$3$4$5$6$7$8'' ); return preg_replace( $search_patterns, $replace_patterns, $string ); }


Esta pregunta es específicamente sobre PHP, pero como esta publicación estuvo en la parte superior de los resultados cuando busqué en Google "minify css regex", estoy publicando una adaptación de Python aquí:

#!/usr/bin/env python # These regexes were adapted from PCRE patterns by Dustin "lots0logs" Falgout, # Matthias Mullie (https://.com/a/15195752/299196), and Andreas # "Qtax" Zetterlund (https://.com/a/44350195/299196). import re CSS_COMMENT_STRIPPING_REGEX = re.compile(r""" # Quoted strings ( "(?:[^"//]+|//.)*" | ''(?:[^''//]+|//.)*'' ) | # Comments //* ( .*? /*/ ) """, re.DOTALL | re.VERBOSE ) CSS_MINIFICATION_REGEX = re.compile(r""" # Quoted strings ( "(?:[^"//]+|//.)*" | ''(?:[^''//]+|//.)*'' ) | # Spaces before and after ";" and "}" /s* ; /s* ( } ) /s* | # Spaces around meta characters and operators excluding "+" and "-" /s* ( [*$~^|]?= | [{};,>~] | !important/b ) /s* | # Spaces around "+" and "-" in selectors only /s*([+-])/s*(?=[^}]*{) | # Spaces to the right of "(", "[" and ":" ( [[(:] ) /s+ | # Spaces to the left of ")" and "]" /s+ ( [])] ) | # Spaces around ":" outside of selectors /s+(:)(?![^/}]*/{) | # Spaces at the beginning and end of the string ^ /s+ | /s+ /z | # Collapse concurrent spaces (/s)/s+ """, re.DOTALL | re.IGNORECASE | re.VERBOSE ) def minify_css(css): return CSS_MINIFICATION_REGEX.sub(r"/1/2/3/4/5/6/7/8", CSS_COMMENT_STRIPPING_REGEX.sub(r"/1", css))

Es posible que no sean exactamente iguales a las versiones de PHP + PCRE. Dado que la biblioteca de expresiones regulares de Python no admite muchas de las construcciones que PCRE hace, tuve que modificar los patrones de PCRE. Los modificadores que eliminé mejoran el rendimiento y potencialmente refuerzan la expresión regular contra la entrada maliciosa, por lo que probablemente no sea una buena idea usar esto en entradas no confiables .