El editor TinyMCE está rompiendo mi hermoso HTML - Soluciones
Este es básicamente un duplicado exacto de: ¿Cómo hacer que Wordpress y TinyMCE acepten etiquetas <a> envolviendo elementos de bloque como permite HTML5? y Problema con HTML5, WordPress y Tiny MCE - envolver un div con una etiqueta anchor produce resultados extraños
Mi problema es que la solución sugerida (filtro tiny_mce_before_init
) no parece resolver mi problema. Tengo HTML que luce así:
<a href="#">
<img src="path/to/file.jpg" />
<p>Algun texto descriptivo increíble</p>
</a>
Esto es perfectamente válido en HTML5. Sin embargo, al editor de WP no le gusta y lo transforma a:
<a href="#">
<img src="path/to/file.jpg" />
</a>
<p>Algun texto descriptivo increíble</p>
Esto, por supuesto, rompe mi diseño. ¿Alguien sabe de alguna manera para prevenir este comportamiento? No puedo renunciar al componente Visual del editor y quedarme con texto plano. Cualquier sugerencia es bienvenida.
Para ser claro, cuando uso el código de abajo (sugerido aquí), las etiquetas <p>
pueden permanecer dentro de los anchors pero se agrega mucho espacio extra junto con una entidad
que se multiplica cada vez que cambias entre los modos Visual y Texto.
add_filter('tiny_mce_before_init', 'modify_valid_children');
function modify_valid_children($settings){
$settings['valid_children']="+a[div|p|ul|ol|li|h1|h2|h3|h4|h5|h5|h6]";
return $settings;
}

Independientemente de lo que hayas configurado como hijos válidos, WordPress maneja las etiquetas p y los saltos de línea de una manera muy particular. Probablemente te hayas dado cuenta, al cambiar del editor de texto al editor visual y viceversa, que tus etiquetas <p>
se eliminan, similar a lo que ocurre en el frontend. Una forma de evitar esto es asignando una clase personalizada a las etiquetas <p>
.
<p class="text">Esta etiqueta p no será eliminada"</p>
.
Mientras que ↑ esto ↑ evitará que se elimine tu etiqueta p, no solucionará tu problema ya que el markup en el frontend seguirá alterándose. Podrías DESACTIVAR wpautop. Si haces eso Y además incluyes p como hijo válido, esto SOLUCIONARÁ TU PROBLEMA.
OPCIÓN 1 : Desactivar Autop y Establecer Hijos Válidos
remove_filter( 'the_content', 'wpautop' );
add_filter('tiny_mce_before_init', 'modify_valid_children', 99);
function modify_valid_children($settings){
$settings['valid_children']="+a[div|p|ul|ol|li|h1|span|h2|h3|h4|h5|h5|h6]";
return $settings;
}
Sin embargo, debo advertirte que en el momento en que cambies del editor HTML de vuelta a TinyMCE, tu HTML será destruido. Una solución alternativa es desactivar TinyMCE completamente para ciertos tipos de contenido, como en la opción 2 a continuación.
OPCIÓN 2 : Desactivar Auto P, TinyMCE, y Establecer Hijos Válidos
remove_filter( 'the_content', 'wpautop' );
add_filter('tiny_mce_before_init', 'modify_valid_children', 99);
function modify_valid_children($settings){
$settings['valid_children']="+a[div|p|ul|ol|li|h1|span|h2|h3|h4|h5|h5|h6]";
return $settings;
}
add_filter('user_can_richedit', 'disable_wyswyg_to_preserve_my_markup');
function disable_wyswyg_to_preserve_my_markup( $default ){
if( get_post_type() === 'post') return false;
return $default;
}
Para la mayoría de las personas, ↑ esto ↑ no es una opción.
¿Qué otras opciones existen? Una solución alternativa que he notado que funciona es usar una etiqueta span con una clase y asegurarse de que no haya espacios en blanco entre tus etiquetas HTML. Si haces esto, puedes usar la opción uno anterior y evitar tener que desactivar TinyMCE por completo. Solo recuerda que también tendrás que agregar algo de CSS a tu hoja de estilos para mostrar el span correctamente.
OPCIÓN 3: Opción 1 + Etiquetas Span con Estilo
HTML
<a href="#"><img src="https://placehold.it/300x200?text=Don%27t+P+On+Me" alt="" /><span class="noautop">Texto descriptivo increíble</span></a>
CSS en la hoja de estilos
.noautop {
display: block;
}
Opción 4: Usar el shortcode integrado del cargador de medios
Inicialmente olvidé esta, pero el shortcode [caption] se verá así:
[caption id="attachment_167" align="alignnone" width="169"]
<img class="size-medium wp-image-167" src="http://example.com/example.png" alt="" width="169" height="300" />
pie de foto increíble
[/caption]
El resultado se verá así:
<figure id="attachment_167" style="width: 169px" class="wp-caption alignnone">
<img class="size-medium wp-image-167" src="http://example.com/example.png" alt="" width="169" height="300" />
<figcaption class="wp-caption-text">Texto descriptivo increíble</figcaption>
</figure>
Si no quieres etiquetas figure, podrías usar un plugin como custom content shortcode que te permite hacer esto:
[raw] <p>este contenido no será filtrado por WordPress</p> [/raw]
¿Por qué el editor no puede simplemente funcionar como yo quiero?
He pasado incontables horas intentando que esto funcione bien a lo largo de los últimos años. Ocasionalmente encuentro una solución que funciona perfectamente, pero luego WordPress lanza una actualización que vuelve a estropear todo. La única solución que he encontrado que funciona completamente como debería, me lleva a la mejor respuesta que tengo.
Opción 5 : Preserved HTML Editor Markup Plus
Así que ahórrate el dolor de cabeza y simplemente usa esto. Por defecto, Preserved HTML Editor Markup Plus solo afecta a nuevas páginas. Si quieres cambiar páginas ya creadas, tienes que ir a www.example.com/wp-admin/options-writing.php y editar los ajustes del plugin. También podrás cambiar el comportamiento predeterminado de los saltos de línea.
Nota: Si decides usar esto, asegúrate de revisar el hilo de soporte cuando se lance una nueva actualización de WordPress. Ocasionalmente, un cambio puede estropear las cosas, así que es mejor asegurarse de que el plugin funciona en las versiones más recientes.
Crédito Extra: Depuración de tu Problema / Edición de Otras Opciones de TinyMCE
Si quieres inspeccionar y editar fácilmente tus configuraciones de TinyMCE manualmente, como lo haces con los filtros, puedes instalar advanced TinyMCE config. Te permite ver TODAS las opciones configuradas de TinyMCE y editarlas desde una interfaz simple. También puedes agregar nuevas opciones, igual que con los filtros. Hace que todo sea mucho más fácil de entender.
Por ejemplo, yo tengo ambos, ese y Preserved HTML Editor Markup Plus. La captura de pantalla a continuación es de la página de administración de Advanced TinyMCE Config. Aunque la captura corta el 90% de lo que realmente hay, puedes ver que muestra los hijos válidos disponibles para editar y cuáles fueron agregados por Preserved HTML Editor Markup Plus.
Esta es una manera extremadamente útil no solo para personalizar completamente tu editor, sino también para ver qué está pasando. Incluso podrías averiguar qué estaba causando tu problema. Después de revisar los parámetros mientras Preserved HTML Editor Markup estaba activado, vi algunas opciones adicionales que podrían agregarse a un filtro personalizado.
function fix_tiny_mce_before_init( $in ) {
// Puedes depurar esto sin necesidad de tener Advanced Tinymce Config activado:
// print_r( $in );
// exit();
$in['valid_children']="+a[div|p|ul|ol|li|h1|span|h2|h3|h4|h5|h5|h6]";
$in[ 'force_p_newlines' ] = FALSE;
$in[ 'remove_linebreaks' ] = FALSE;
$in[ 'force_br_newlines' ] = FALSE;
$in[ 'remove_trailing_nbsp' ] = FALSE;
$in[ 'apply_source_formatting' ] = FALSE;
$in[ 'convert_newlines_to_brs' ] = FALSE;
$in[ 'verify_html' ] = FALSE;
$in[ 'remove_redundant_brs' ] = FALSE;
$in[ 'validate_children' ] = FALSE;
$in[ 'forced_root_block' ]= FALSE;
return $in;
}
add_filter( 'tiny_mce_before_init', 'fix_tiny_mce_before_init' );
Desafortunadamente, este método no funcionó. Probablemente haya algún regex o JavaScript que se ejecuta al actualizar la entrada y/o cambiar entre editores. Si echas un vistazo al código fuente de Preserved HTML Editor, puedes ver que hace algún trabajo de JavaScript en el lado del administrador, así que mi último consejo sería revisar cómo funciona el plugin si quieres agregar esta funcionalidad en tu tema.
De todos modos, lo siento por cualquiera que haya llegado hasta aquí en mi respuesta. Solo pensé en compartir mis propias experiencias lidiando con el editor de WordPress, para que otros no tengan que pasar horas intentando resolver esto como yo lo hice.

Gracias por detectar ese error tipográfico en mi ejemplo HTML (edité la pregunta). Para ser claro, el HTML real en cuestión no tiene ese problema. Revisaré el plugin que mencionaste.

¡Espero que esto te ayude Dominic! Una última cosa que me gustaría mencionar es que puedes agregar leyendas en WordPress a través del cargador de medios. Además, creo que semánticamente la forma correcta de hacerlo es así. http://www.w3schools.com/tags/tag_figcaption.asp

Eso es una idea interesante. No había considerado marcarlo como una figura y leyenda. Voy a intentarlo.

Solo para cerrar esto. Terminé usando etiquetas <span>
. Odio que mi marcado ahora dependa de los espacios en blanco, pero fue el camino de menor resistencia por ahora. Probé con <figcaption>
pero es un elemento a nivel de bloque, y TinyMCE no permitía que las etiquetas <a>
lo envolvieran, así que volví al punto de partida. Gracias de nuevo por todas las ideas.

Dominic, revisa la opción 4 de arriba si quieres usar <figure>
. ¡Se me olvidó por completo que el shortcode de caption integrado hace esto por defecto!

Bryan, esa es una buena idea, pero todavía necesito que todo el <figure>
sea clickeable, así que vuelvo a envolverlo en una etiqueta <a>
(o usar múltiples etiquetas <a>
lo cual preferiría no hacer).

Sí, buena idea. Por cierto, si nunca has probado Custom Content Shortcode, te recomendaría que lo pruebes. Fácilmente el plugin más útil que tengo, especialmente cuando se trata de estos problemas.

En primer lugar: Muchas gracias por la excelente respuesta de Bryan, que también documenta las dificultades que encontró.
Como resultado de mis propios experimentos (incluyendo algunas de las sugerencias de Bryan), creo que el siguiente plugin podría ayudar enormemente a mantener la consistencia al cambiar entre el editor HTML y el visual: Advanced Editor Tools (anteriormente TinyMCE Advanced) - https://wordpress.org/plugins/tinymce-advanced/.
A primera vista, el plugin no hacía lo que esperaba. En un segundo intento, encontré un parámetro de configuración llamado "preservar etiquetas de párrafo". El editor visual ya no elimina las etiquetas <p>
y <br>
del editor HTML. Incluso más: después de cambiar entre ambos editores, noté que casi todas las líneas vacías habían desaparecido y en su lugar se habían insertado muchas etiquetas <p>
y </p>
.
El inconveniente es que la representación visual en el editor visual muestra algunos pequeños defectos, pero eso se considera un problema menor. Para mí lo que cuenta es esto: Sabes exactamente dónde está el cursor, gracias a un comportamiento casi WYSIWYG. Después de todo: incluso sin esta configuración específica, el editor visual tiene fallos de renderizado comparado con la vista previa/resultado final.
Siento que ahora tengo un control bastante completo sobre el espaciado en el texto. Incluso cuando presiono Enter en el editor visual (o Shift+Enter), se generan las etiquetas adicionales. Otro inconveniente: Solo ves eso en la vista HTML (y en el resultado final) - el editor visual no muestra el espacio adicional. ¿Y qué? ¡Lo importante es que ya no está arruinando mi hermoso HTML!
