Evitar que WordPress envuelva las imágenes en etiquetas "P"

17 ene 2011, 06:08:51
Vistas: 34.3K
Votos: 39

He buscado por todas partes una solución simple para esto, pero sin éxito. WordPress sigue envolviendo mis imágenes en etiquetas p y debido a la naturaleza excéntrica del diseño del sitio en el que estoy trabajando, esto es muy molesto.

He creado una solución con jQuery para desenvolver las imágenes, pero no es muy buena. Se retrasa debido a otras cosas que se cargan en la página y por lo tanto los cambios son lentos. ¿Hay alguna manera de evitar que WordPress envuelva solo las imágenes con etiquetas p? Tal vez un hook o filtro que se pueda ejecutar.

Esto sucede cuando se sube una imagen y luego se inserta en el editor WYSIWYG. Ir manualmente a la vista de código y eliminar las etiquetas p no es una opción ya que el cliente no tiene esos conocimientos técnicos.

Entiendo que las imágenes son elementos en línea, pero por la forma en que he codificado el sitio, las imágenes están dentro de divs y configuradas como block, por lo que son código válido.

1
Todas las respuestas a la pregunta 11
11
41

Aquí está lo que hicimos ayer en el sitio de un cliente con el que teníamos este mismo problema... Creé un filtro rápido como plugin y lo activé.

<?php
/*
Plugin Name: Eliminador de etiquetas P en imágenes
Description: Plugin para eliminar etiquetas p alrededor de imágenes en el contenido, después de que el filtro autop de WP las haya añadido. (qué ironía)
Version: 1.0
Author: Fublo Ltd
Author URI: http://fublo.net/
*/

function filter_ptags_on_images($content)
{
    // realizar un reemplazo con expresión regular...
    // encontrar todas las etiquetas p que solo contengan
    // <p>quizá algo de espacio en blanco<img todo hasta /> luego quizá espacio en blanco </p>
    // reemplazarlo solo con la etiqueta de imagen...
    return preg_replace('/<p>(\s*)(<img .* \/>)(\s*)<\/p>/iU', '\2', $content);
}

// queremos que se ejecute después del filtro autop... 10 es el valor por defecto.
add_filter('the_content', 'filter_ptags_on_images');

Si colocas eso en un archivo php dentro de tu carpeta /wp-content/plugins y luego lo activas, debería eliminar las etiquetas p de cualquier párrafo que solo contenga una imagen.

No estoy seguro de lo fuerte que es la expresión regular en términos de si fallará con salidas de otros editores - por ejemplo, si la etiqueta img se cierra solo con > fallará. Si alguien tiene algo más robusto, sería de gran ayuda.

Saludos,

James

--- Filtro mejorado ---

Para funcionar con imágenes envueltas en enlaces, mantiene los enlaces en la salida y elimina las etiquetas p.

return preg_replace('/<p>\s*(<a .*>)?\s*(<img .* \/>)\s*(<\/a>)?\s*<\/p>/iU', '\1\2\3', $content);
2 feb 2011 14:26:35
Comentarios

Sin lugar a dudas, esta es la respuesta correcta. Gracias James, lo probé y funciona increíblemente bien.

Dwayne Charrington Dwayne Charrington
3 feb 2011 05:25:38

Hola @Dwayne - gracias por tus comentarios. He añadido un filtro mejorado que manejará los enlaces, ahora lo estamos usando en el sitio de nuestro cliente.

jamesc jamesc
4 feb 2011 19:29:20

Definitivamente deberías publicar esto en el repositorio de plugins de Wordpress. Una búsqueda rápida en Google muestra que mucha gente tiene este problema sin una buena solución.

Geoffrey Burdett Geoffrey Burdett
29 ago 2014 16:19:28

Ten en cuenta que esto no funcionará con el marcado HTML5 predeterminado de img, es decir, <img ...> sin la barra diagonal de cierre. Es mejor hacer que sea opcional en tu expresión regular. O mejor aún, puedes omitirlo ya que .* se encargará de ello.

Bram Vanroy Bram Vanroy
10 mar 2015 21:41:31

¿Alguien ha logrado que funcione para <img ...> sin />?

Runnick Runnick
17 dic 2017 15:41:26

Por cierto, esto parece no funcionar con Gutenberg.

jarrodwhitley jarrodwhitley
14 mar 2019 17:06:43

Esto no funciona si hay texto dentro del párrafo.

Justin Putney Justin Putney
1 may 2021 01:23:57

El siguiente código funcionó para sacar una imagen <img> de un párrafo <p> incluso si va seguida de texto: return preg_replace('/<p>(\s*)(<img .*>)/iU', "$2<p>", $content);

Justin Putney Justin Putney
1 may 2021 02:30:19

Funciona perfectamente... Gracias

Dushan Dushan
24 nov 2021 17:57:53

@jamesc ¿Cómo se podría ampliar esto para hacer lo mismo con otros elementos, como <iframe>?

Robert Andrews Robert Andrews
31 mar 2022 15:19:49

@RobertAndrews No tengo idea, me temo - no he trabajado con Wordpress en casi 10 años.

jamesc jamesc
1 abr 2022 13:42:40
Mostrar los 6 comentarios restantes
2
13

Básicamente, necesitas hacer que WordPress trate a img como un elemento a nivel de bloque para fines de formato. Estos elementos están codificados directamente en wpautop() y la lista desafortunadamente no se puede filtrar.

Lo que yo haría es:

  1. Hacer un fork de wpautop() con un nombre diferente.
  2. Añadir img a la expresión regular en la variable $allblocks.
  3. Eliminar wpautop del filtro the_content.
  4. Añadir tu versión modificada a the_content.
  5. Puede que necesites ajustar la prioridad y posiblemente eliminar y volver a añadir otros filtros si algo se rompe debido al cambio en el orden de procesamiento.
17 ene 2011 10:33:24
Comentarios

Voy a probar este enfoque. Nunca se me ocurrió agregar la etiqueta img a la variable allblocks, es una idea genial. Veré cómo me va.

Dwayne Charrington Dwayne Charrington
17 ene 2011 12:51:15

Funcionó bien al principio, pero luego me encontré con el escenario cuando una imagen está dentro de una etiqueta de anclaje y ambas ya están dentro de un párrafo (es decir, p > img > a). Al tratar img como un bloque, wp-autop cierra la etiqueta de párrafo antes de que comience la etiqueta img, lo que arruina el diseño.

benz001 benz001
19 jul 2014 05:53:38
1

quizás esto te ayude

remove_filter('the_content', 'wpautop')

Pero entonces tendrás que añadir los párrafos manualmente para todo lo demás.

17 ene 2011 09:54:43
Comentarios

Consideré este enfoque, pero debido a que el diseño es excéntrico como mencioné, depende en gran medida de necesitar etiquetas p. Estoy haciendo un diseño de texto de 2 columnas donde las etiquetas p están flotando a la izquierda para dar la apariencia de 2 columnas de texto. Entonces puedes ver por qué una etiqueta p envolviendo una imagen sería un problema porque también la estaría flotando.

Dwayne Charrington Dwayne Charrington
17 ene 2011 12:49:47
0

Esta publicación es un poco antigua, pero existe una solución mucho más simple, excluyendo el CSS de tu parte.

Envolver la etiqueta img en un div tiene poco efecto negativo.

19 ago 2011 21:48:51
2

Soska ha proporcionado una forma fácil.

Pero lo que hago es extraer la imagen del contenido y mostrarla por separado.

17 ene 2011 11:46:33
Comentarios

También consideré esta opción y sigue siendo una posibilidad. Sin embargo, como es solo una imagen para evitar toda la complicación, podría simplemente usar miniaturas de entradas destacadas que me permitirían controlar cómo se muestra la imagen.

Dwayne Charrington Dwayne Charrington
17 ene 2011 12:52:12

También puedes agregar un campo personalizado a la entrada/página, como imagen miniatura y guardar la ruta de la imagen en su valor...

Avinash Avinash
17 ene 2011 13:09:48
1

Desarrollé un plugin que soluciona este problema exacto: http://wordpress.org/extend/plugins/unwrap-images/

Es mejor que configurar márgenes o meterse directamente en el código de WordPress para aquellos que no quieren lidiar con código, ya que utiliza la función nativa unwrap de jQuery para eliminar las etiquetas p que envuelven a las imágenes.

¡Espero que esto le ayude a alguien! Saludos, Brian

4 nov 2011 10:18:42
Comentarios

aparentemente todavía tiene más de 30 instalaciones activas :D

Julix Julix
6 may 2019 21:41:31
0

La respuesta aceptada me ayudó solo con las imágenes, pero el código revisado no maneja bien las imágenes enlazadas en mi sitio. Esta publicación de blog tiene un código que funciona perfectamente.

Aquí está el código:

function wpautop_forked($pee, $br = 1) {

if ( trim($pee) === '' )
return '';
$pee = $pee . "\n"; // para facilitar las cosas, rellenamos el final
$pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee);
// Espaciar un poco los elementos
$allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li
|pre|select|option|form|map|area|blockquote|img|address|math|style|input
|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer
|nav|figure|figcaption|details|menu|summary)';
$pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee);
$pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
$pee = str_replace(array("\r\n", "\r"), "\n", $pee); // saltos de línea multiplataforma
if ( strpos($pee, '<object') !== false ) {
$pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // no contenido dentro de object/embed
$pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee);
}
$pee = preg_replace("/\n\n+/", "\n\n", $pee); // manejar duplicados
// crear párrafos, incluyendo uno al final
$pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY);
$pee = '';
foreach ( $pees as $tinkle )
$pee .= '<p>' . trim($tinkle, "\n") . "</p>\n";
$pee = preg_replace('|<p>\s*</p>|', '', $pee); // en ciertas condiciones extrañas podría crear un P de solo espacios
$pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee);
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // no aplicar formato a una etiqueta
$pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problema con listas anidadas
$pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
$pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee);
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee);
if ($br) {
$pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', create_function('$matches', 'return str_replace("\n", "<WPPreserveNewline />", $matches[0]);'), $pee);
$pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // opcionalmente crear saltos de línea
$pee = str_replace('<WPPreserveNewline />', "\n", $pee);
}
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee);
$pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee);
if (strpos($pee, '<pre') !== false)
$pee = preg_replace_callback('!(<pre[^>]*>)(.*?)</pre>!is', 'clean_pre', $pee );
$pee = preg_replace( "|\n</p>$|", '</p>', $pee );

return $pee;
}

remove_filter('the_content', 'wpautop');
add_filter('the_content', 'wpautop_forked');

¡Saludos!

1 ene 2012 15:19:51
2

No soy un experto pero pasé toda la tarde intentando resolver el problema de las imágenes envueltas en etiquetas p y esto funcionó para mí.

Estoy trabajando en un tema basado en WordPress y simplemente agregué esto al archivo functions.js

Función jQuery unwrap

> $(document).ready(function (){
> 
> // para imágenes envueltas en etiquetas a
> 
> $(‘.entry a’).unwrap(‘p’);
> 
> // para imágenes envueltas solo en etiquetas p
> $(‘.entry img’).unwrap(‘p’);

Ahora puedo trabajar con las etiquetas p e img por separado.

También se puede agregar un div con una clase diferente alrededor de la imagen usando esto:

$(document).ready(function (){

$('.entry img').wrap('<div class="justImg"></div>');

Esta última no resolvió mi problema porque quería hacer que las etiquetas p tuvieran display:none;, así que realmente tuve que sacar esas imágenes de ahí.

18 feb 2013 20:29:02
Comentarios

¿Realmente usas comillas rizadas? :)

fuxia fuxia
18 feb 2013 21:05:06

Consideré este enfoque inicialmente hace tiempo, pero la idea de manipular el DOM innecesariamente mediante jQuery representaba demasiado riesgo y una sobrecarga potencialmente innecesaria cuando puedes hacerlo en PHP con expresiones regulares complejas.

Dwayne Charrington Dwayne Charrington
20 feb 2013 01:29:26
0

Coloca tu imagen dentro de una etiqueta <div>, sin ningún carácter de espacio en blanco entre ellas. Así que en lugar de:

<div class="your_container">
    <div class="element1">...</div>
    <div class="element2">...</div>
    <img src="image.jpg" />
</div>

Escribe esto:

<div class="your_container">
    <div class="element1">...</div>
    <div class="element2">...</div>
    <div><img src="image.jpg" /></div>
</div>

He tenido el mismo problema con elementos <a>, y esto lo solucionó para mí.

19 sept 2020 17:33:17
2

Dependiendo de la entrada, otra solución podría ser usar el plugin WP Unformatted para desactivar la función auto-p en una base por entrada.

23 feb 2011 03:33:35
Comentarios

Eso es bastante útil, aunque la única advertencia que puedo ver es que si quieres que las imágenes no tengan etiquetas P pero también tener texto dentro de tu página, va a ser un gran desorden. Probablemente sería bueno para publicaciones que solo tienen imágenes y tal vez unas pocas líneas de texto. Aún así, útil.

Dwayne Charrington Dwayne Charrington
23 feb 2011 03:59:05

Sí, por eso dije que depende de la publicación.

Synetech Synetech
23 feb 2011 04:48:42
0

En caso de que alguien esté buscando una forma rápida y sucia de solucionar esto para cualquier etiqueta, esto es lo que hice:

  1. Ve a wp-content/formatting.php
  2. Busca la función wpautop. (por si no lo pillaste, es WP-AUTO-P, ¿entiendes?)
  3. Busca la variable "all blocks", debería ser algo como $allblocks = '(?:table|thead|tfoot|capti...
  4. Al final añade el bloque que quieras omitir - img, a, etc... Por ejemplo, si termina en (...)menu|summary)'; cámbialo a (...)menu|summary|a)'; para añadir la etiqueta a y evitar que le aplique el autopeeing. ¡Fíjate en el separador de barra vertical | - es sintaxis de regex!

¡Eso es todo, feliz WordPresseo!

12 ago 2018 01:04:00