¿Maneras de manejar la representación SVG en WordPress?

9

Con el avance de los navegadores de Internet, me siento cada vez más cómodo usando SVGS al codificar sitios web ... especialmente para iconos y gráficos simples que pueden reemplazarse sobre la marcha por pngs.

Parece que WordPress casi es compatible con SVGS. Digo casi porque:

  1. No es por defecto un tipo de archivo permitido en WordPress. Por lo tanto, debe agregar eso antes de cargar SVG

  2. No puede ver una miniatura SVG en la galería de medios. (ver imagen a continuación)

  3. A veces, cuando lo agrega al editor (a través del botón Agregar medios), el editor no conoce el tamaño de svg, por lo que aunque agrega el svg como imagen, tiene un ancho y una altura de cero.

  4. Cuando hace clic en "editar imagen" desde la ventana emergente de carga de medios, aparece un mensaje que dice "la imagen no existe". Ver imagen a continuación.

Estoy de acuerdo con el elemento 1 de esta lista, pero ¿alguien ha descubierto cómo corregir los elementos 2 3 y 4?

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Actualización sobre el elemento 1:

Para permitir un nuevo tipo MIME (como SVG), simplemente puede agregar un gancho en functions.php

function allow_new_mime_type($mimes) {

    $mimes['svg'] = 'image/svg+xml';

    return $mimes;
}
add_filter( 'mime_types', 'allow_new_mime_type' );

Ahora debería poder cargar SVG. Puede encontrar más información en este tutorial . Esto solo resuelve el elemento 1, que como mencioné antes, no es un problema para mí (aunque creo que debería estar permitido por defecto).

Actualización sobre el elemento 2:

Investigué un poco y rastreé la función que decide si un archivo adjunto es una imagen o no. Parece que todo se reduce a esta función en wp-includes / post.php

/**
 * Check if the attachment is an image.
 *
 * @since 2.1.0
 *
 * @param int $post_id Attachment ID
 * @return bool
 */
function wp_attachment_is_image( $post_id = 0 ) {
    $post_id = (int) $post_id;
    if ( !$post = get_post( $post_id ) )
        return false;

    if ( !$file = get_attached_file( $post->ID ) )
        return false;

    $ext = preg_match('/\.([^.]+)$/', $file, $matches) ? strtolower($matches[1]) : false;

    $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' );

    if ( 'image/' == substr($post->post_mime_type, 0, 6) || $ext && 'import' == $post->post_mime_type && in_array($ext, $image_exts) )
        return true;
    return false;
}

Como puede ver, hay una serie de extensiones de imagen válidas definidas en esta función. No veo ningún filtro que pueda usarse para modificar esa matriz. Pero eso es un comienzo ...

Sin embargo, no estoy seguro de por qué la última declaración if devuelve false para svgs. Incluso si no agrego la extensión svg a la matriz $ image_exts, la primera condición debería ser verdadera, ¿no?

if ( 'image/' == substr($post->post_mime_type, 0, 6)

Eso comprueba si 'image /' es igual a los primeros seis caracteres en el tipo mime, que para svg es image / svg + xml (los primeros seis son "image /").

ACTUALIZAR

Tras una investigación más profunda, parece que el problema no es con wp_attachment_is_image en absoluto, sino porque el tamaño de la imagen (ancho y alto) no se agrega a los metadatos del archivo adjunto cuando se carga el SVG. Esto se debe a que la función para calcular la imagen utilizada es la función php getimagesize (), que no devuelve un tamaño de imagen para SVG. Encontré una respuesta en stackoverflow sobre la función getimagesize y sobre cómo se comportan los svgs. Véalo aquí.

gdaniel
fuente
Instale el complemento de soporte SVG, muestra el svg en la galería de medios - wordpress.org/plugins/svg-support
Nuno Sarmento

Respuestas:

10

Eche un vistazo a wp_prepare_attachment_for_js(), que es lo que recopila metadatos de archivos adjuntos para su uso en las páginas de medios. El filtro homónimo nos permite agregar o alterar metadatos.

El siguiente ejemplo se puede soltar en functions.php. Nota: esto requiere soporte SimpleXML en PHP.

function common_svg_media_thumbnails($response, $attachment, $meta){
    if($response['type'] === 'image' && $response['subtype'] === 'svg+xml' && class_exists('SimpleXMLElement'))
    {
        try {
            $path = get_attached_file($attachment->ID);
            if(@file_exists($path))
            {
                $svg = new SimpleXMLElement(@file_get_contents($path));
                $src = $response['url'];
                $width = (int) $svg['width'];
                $height = (int) $svg['height'];

                //media gallery
                $response['image'] = compact( 'src', 'width', 'height' );
                $response['thumb'] = compact( 'src', 'width', 'height' );

                //media single
                $response['sizes']['full'] = array(
                    'height'        => $height,
                    'width'         => $width,
                    'url'           => $src,
                    'orientation'   => $height > $width ? 'portrait' : 'landscape',
                );
            }
        }
        catch(Exception $e){}
    }

    return $response;
}
add_filter('wp_prepare_attachment_for_js', 'common_svg_media_thumbnails', 10, 3);
Josh
fuente
2

Esto no es algo que pueda "piratear" fácilmente con un complemento o algún pequeño conjunto de código.

En resumen, los SVG, en general, no son "imágenes" en el sentido de todas las imágenes que le han precedido. Los SVG son imágenes basadas en vectores, y las primeras en obtener una tracción real en la web.

Todas las imágenes anteriores han sido basadas en mapas de bits. El sistema de manejo de imágenes de WordPress fue escrito específicamente para tratar con ellos, y este diseño inherente se encuentra en cada punto del sistema.

Es una suposición subyacente que las imágenes tienen anchuras y alturas, por ejemplo. Los SVG no tienen ninguno, pueden ser de cualquier tamaño. Hay todo un "editor" básico para imágenes integradas en WordPress, ninguna de las funciones que realmente puede aplicarse a los SVG.

El sistema multimedia se está reconstruyendo lentamente, con el énfasis aquí en "lentamente". Se debe mantener una gran cantidad de compatibilidad con versiones anteriores y se deben implementar nuevos diseños. Además, la mayoría de las personas están mucho más interesadas en admitir videos, audio y listas de reproducción. A medida que se realiza este trabajo de rediseño, y las secciones de la biblioteca se vuelven más abstractas, entonces este tipo de cosas será más fácil de soportar con el tiempo. Pero todavía no está allí, y no lo estará por un tiempo. Esta es la razón por la cual no se admite el tipo mime SVG, porque agregar ese tipo mime hasta que todas las piezas subyacentes funcionen sería un camino hacia la rotura.

Para los SVG, wp_attachment_is_imagedebería devolver falso, ya que wp_attachment_is_imagese utiliza para determinar si se muestra o no el botón del editor y si se image_downsizeintenta cambiar el tamaño de la imagen en las miniaturas y demás. Ninguno de los dos funcionaría para SVG de todos modos. Para admitir correctamente los SVG, necesitaría escribir un nuevo sistema para agregar metadatos para esas imágenes por completo, y luego agregar soporte para todos los lugares en los que se podrían usar los metadatos. Como puedes imaginar, ese no es un trabajo pequeño.

Otón
fuente
1
Los SVG tienen tamaño (ventana gráfica y cuadro de vista), es simplemente más "virtual" que las dimensiones fijas dependientes de píxeles de los mapas de bits.
Rarst
1

Solo leyendo la fuente (no probando), puedo ver que la extensión debe coincidir:

if ( 'image/' == substr($post->post_mime_type, 0, 6) || $ext && 'import' == $post->post_mime_type && in_array($ext, $image_exts) )

que se lee como (pseudocódigo)

si image/son los primeros 6 caracteres en la propiedad $ post object post_mime_type O hay una extensión O importes la propiedad $ post objects post_mime_type Y la extensión del archivo actual es uno de (Array)

Y eso significa que la última declaración siempre decidirá si el ifresultado es verdadero o no.

Por lo que puedo leer get_attached_file(), hay un filtro que permitiría falsificar la extensión:

return apply_filters( 'get_attached_file', $file, $attachment_id );

En otras palabras, podría intentar devolver el mismo archivo pero con una extensión diferente. No entraría en conflicto con otras partes, ya que el wp_attachment_is_image()justo vuelve bool.

emperador
fuente