Presentamos el puente React-Gutenberg: compatibilidad con bloques sin cabeza para una experiencia de edición aún mejor
Publicado: 2023-04-09Está entusiasmado con las oportunidades que ofrece WordPress sin cabeza, pero el equipo de marketing de su cliente está vinculado al editor WYSIWYG Gutenberg.
Vea cómo el nuevo soporte de bloque de Gutenberg de Faust para proyectos sin cabeza une los dos para modernizar su desarrollo mientras empodera a sus especialistas en marketing.
Altavoces:
- Teresa Gobble, ingeniera de software en WP Engine
- Blake Wilson, ingeniero de software sénior en WP Engine
Diapositivas de la sesión:
Transcripción:
TERESA GOBBLE: Hola amigos. Mi nombre es Teresa Gobble. Soy ingeniero de software con WP Engine y trabajo en el equipo de Faust.
Y estoy aquí con Blake Wilson, un ingeniero de software sénior, para presentarles React-Gutenberg Bridge: compatibilidad con bloques sin cabeza para una experiencia de edición aún mejor. Bienvenido. Empecemos.
Así que hoy, tenemos mucho que cubrir. En primer lugar, repasaré un par de cosas relacionadas con el problema y la solución que tenemos para usted, así como el valor de React-Gutenberg Bridge. Luego iremos a Blake, quien nos proporcionará una demostración del puente React-Gutenberg en acción. Después, hablaremos de un par de detalles técnicos. Y también visitaremos una hoja de ruta futura de lo que tenemos reservado para esto.
Así que aquí está el problema. No existe una forma simplificada de traducir los bloques de Gutenberg de WordPress a un front-end sin cabeza. Las soluciones que existen aún no son escalables ni intuitivas para proporcionar una experiencia de desarrollador que los desarrolladores autónomos puedan esperar.
El desacoplamiento interrumpe la capacidad de usar el contenido del bloque de Gutenberg en el editor de forma natural. Y las agencias se preguntan cómo hacen para hacerlo a su manera o desde cero con poca orientación. Y quedan muchas preguntas sin respuesta para la gente.
¿Qué pasa con el estilo? ¿Qué pasa con la reutilización, los bloques dinámicos, InnerBlocks? Bueno, aquí es donde entra en juego React-Gutenberg Bridge. Es una solución en dos partes: primero, una forma de exponer mediante programación los bloques de Gutenberg para que puedan analizarse y leerse en el front-end sin cabeza. Esta pieza se llama WPGraphQL Content Blocks.
En segundo lugar, tenemos un conector para facilitar la configuración y el renderizado de esos bloques en el front-end sin cabeza. Y este es un paquete llamado Faust WP Blocks. Aquí verá un tutorial de cómo funciona con estas dos piezas de solución.
El back-end basado en React de su sitio web tiene sus Bloques Gutenberg, que están expuestos por el complemento WPGraphQL Content Blocks. Expone el contenido de block.json a WPGraphQL. Se lo proporciona al complemento, llamado WPGraphQL.
Y luego llega el paquete del conector, que permite la personalización, el descubrimiento y la representación de bloques. Y esto se discutirá mucho más a medida que avancemos en la discusión técnica y la demostración de hoy. Entonces, ¿qué tipo de valor aporta esto a su equipo?
Bueno, es una solución obstinada de extremo a extremo, que reduce la complejidad y la ambigüedad. Ahorra tiempo de desarrollo al seguir convenciones específicas. Permite combinar bloques y patrones de bloques. Y se puede reutilizar una y otra vez. Ahora que tiene una idea de cómo funciona el puente React-Gutenberg, vayamos a Blake para ver una demostración en acción.
BLAKE WILSON: Gracias, Teresa. Hola a todos. Soy Blake Wilson. Soy un ingeniero de software sénior aquí en WP Engine.
Y estoy en el equipo Faust JS construyendo Faust. Tengo una demostración realmente genial para ustedes hoy que muestra los dos componentes que hemos creado para ayudar a orquestar este puente React-Gutenberg. Así que vamos a entrar en materia.
Para empezar, te mostraré lo que tengo aquí para mi configuración. Y luego podemos entrar en el código real y ver lo que tenemos allí. Entonces, para empezar, tengo un sitio de WordPress aquí que se ejecuta en Local.
Tengo algunos complementos instalados. Así que tengo el complemento Faust. Esto ayuda a facilitar las vistas previas y todo ese tipo de cosas buenas en su sitio de Faust JS. Tengo WPGraphQL, que es necesario para transformar su sitio de WordPress en un punto final de GraphQL.
Y luego tengo WPGraphQL Content Blocks. Este es uno de los complementos que hemos creado para ayudar a facilitar este puente React-Gutenberg. Esta solución consta de dos partes principales.
Así que tenemos una de las piezas para exponer los datos de Gutenberg Block mediante programación a través de WPGraphQL, y luego otra parte para consumir eso en su front-end de Faust JS. Comencemos por echar un vistazo a los bloques de contenido de WPGraphQL y cómo funcionan.
Así que iremos a nuestro IDE gráfico. Y tengo esta consulta configurada aquí para tomar los datos de una página. Entonces, en este caso, solo obtenemos el título de la página.
Entonces, lo que hace GraphQL Content Blocks es exponer un tipo de bloques de contenido en su esquema GraphQL. Entonces, si escribimos bloques de contenido, puede ver aquí, obtenemos información para esta página determinada y todos los bloques en esta página. Repasemos y editemos esta página y agreguemos algo de contenido.
Así que iremos a la página de muestra. Y pueden ver aquí que tenemos una pizarra en blanco. Así que sigamos adelante y creemos algunos bloques. Vamos a crear algunas columnas aquí.
Y haremos una columna 50/50. Agreguemos un párrafo en esta mitad, y luego en una imagen en esta mitad. Así que tengo una imagen aquí en mi biblioteca de medios. Sigamos adelante y entreguemos esto.
Y pueden ver aquí, tenemos dos columnas. Nuevamente, un párrafo a la izquierda y una imagen a la derecha. Así que actualicemos esto. Y volvamos a WPGraphQL Content Blocks y veamos qué obtenemos como resultado.
Como pueden ver aquí, ahora tenemos dos bloques de contenido. La primera aquí es una columna central, columna central. Y luego obtenemos HTML renderizado dentro de eso.
Entonces, lo mejor de WPGraphQL Content Blocks es que también manejamos InnerBlocks. Entonces puede ver aquí que si agregamos un parámetro a los bloques de contenido llamado flat true, puede ver que ahora obtenemos todos los bloques que estaban incluso en esas columnas. Así que estamos manejando ese caso por ti también.
Obtenemos una columna central, columna central, párrafo central, imagen central. Así que todo eso se hace programáticamente para usted. Y ahora, puede usar estos datos de bloque en su interfaz. Así que profundicemos un poco más aquí.
Digamos que queremos algunos de los atributos en eso. Podemos usar eso usando una unión en GraphQL. Así que lo haremos en la imagen central, obtendremos los atributos. Y digamos que queremos el título, por ejemplo.
Así que pueden ver aquí que no hay subtítulos. Volvamos a nuestra página de muestra. Continuaremos y agregaremos un título aquí. Mi subtítulo. Actualiza eso.
Y si actualizamos esta consulta, podemos ver ahora que obtenemos mi título como un atributo adecuado en los bloques de contenido de WPGraphQL. Así que esta es la parte 1 de la solución. Ahora, podemos obtener todos nuestros datos de Gutenberg Block y usarlos para consumirlos en nuestra interfaz.
Vayamos a VS Code y veamos cómo abordamos esa pieza. Así que este es un proyecto de ejemplo de Faust JS que preparé. Es muy sencillo. Se basa en Faust Scaffold Blueprint, pero con alguna configuración adicional para manejar estos bloques.
Entonces, si echamos un vistazo al paquete JSON, puede ver aquí que tenemos algunas dependencias aquí, algunos de los paquetes habituales de Faust, como core y CLI. También disponemos de Bloques Faust VP. Así que este es uno de esos paquetes que proporciona todas nuestras funciones auxiliares.
También tenemos algunas dependencias de WordPress para manejar estilos, etc. También notará aquí que tenemos este directorio de WP Blocks. Entonces, aquí es donde viven todos nuestros bloques para nuestra interfaz, y actúa como un registro para todos los bloques que usamos en nuestra interfaz.
Puede ver que tenemos un archivo index.js. Y esto es esencialmente un objeto que determina todos los bloques que estamos usando en nuestro front-end. Así que pueden ver aquí, tenemos el párrafo central, la columna central, las columnas centrales y la imagen central.
En términos de configurar esto, hay dos piezas principales de las que vamos a hablar. Entonces, uno es el proveedor de Bloques de WordPress y el visor de Bloques de WordPress. Así que echemos un vistazo a cómo se ve eso en acción. Primero echemos un vistazo al proveedor de bloques de WordPress.
Y esto estará disponible en pages_app. Entonces puede ver que aquí tenemos este componente, este proveedor, el proveedor de bloques de WordPress. Y acepta un accesorio de configuración que acepta bloques. Entonces puede ver aquí que estamos importando bloques de WP Blocks, el índice de este directorio, y lo estamos pasando al objeto de configuración.
Entonces, esencialmente, lo que esto dice es que el proveedor de bloques de WordPress envuelve toda su aplicación y brinda contexto para todos estos bloques a toda su aplicación. Ahora, entremos en Plantillas WP en nuestra plantilla singular. Y puede ver aquí que estamos llamando al visor de bloques de WordPress con un accesorio de bloques de contenido. Estos son los datos de bloque que obtenemos de WPGraphQL.
Muy bien, eso es suficiente sobre la configuración. Hagamos girar esto y veamos cómo se ve en acción. Así que voy a ejecutar NPM run dev, que configurará un entorno de desarrollo en localhost 3000. Y la página en la que estábamos trabajando antes era una página de muestra de barras, así que visitaré la página de muestra de barras de localhost 3000 para ver esos Gutenberg Bloques que configuramos antes.
Así que puedes ver aquí, tenemos los bloques que son iguales en nuestro editor de Gutenberg. Así que volvamos a nuestro editor de Gutenberg para la página de muestra. Y pueden ver que tenemos nuestras dos columnas aquí, este es mi párrafo, y luego nuestra imagen, que corresponde a lo que tenemos aquí en nuestro frente.
Así que podrías estar diciendo que se ve muy bien y todo, pero ¿podemos modificar los estilos? ¿Podemos cambiar el tamaño de fuente? Seguro que puedes.
Así que volvamos a nuestro editor de Gutenberg y hagamos algunas modificaciones a estos bloques. Así que agreguemos un color de fondo aquí a nuestro párrafo. También cambiemos el tamaño a grande. Para esta imagen aquí, hagámosla redondeada.
Quitemos el subtítulo. Y lo actualizaremos. Y puede ver aquí que ahora se aplican esos estilos. Y puedes verlos en tu frente.
Así que realmente estamos devolviendo la experiencia de editor que no espera en WordPress a su sitio de WordPress sin cabeza. Otra gran cosa acerca de esto es que ahora que está obteniendo datos programáticos para estos bloques, puede hacer su componente React con características específicas del marco, como la siguiente imagen. Ahora, en lugar de solo representar el HTML que obtiene de WPGraphQL, ahora podemos usar esos datos programáticos para crear un componente que represente todas nuestras imágenes en Gutenberg con la siguiente imagen, lo que nos brinda una carga diferida, un mejor rendimiento y mejores imágenes optimizadas. en general, creando una mejor experiencia de usuario para nuestros usuarios.
Así que esto es genial. Estamos viendo exactamente lo que esperamos en nuestro editor de Gutenberg, pero digamos que agregamos un componente que tal vez aún no sea compatible o que no hayamos configurado en nuestro sitio de Faust. Así que sigamos adelante y creemos un nuevo componente aquí abajo. Usaremos la tabla.
Y haremos dos filas: fila 1, fila 2. Vaya y actualice eso. Y si miramos hacia atrás en nuestro código aquí, podemos ver que tenemos cuatro bloques definidos: párrafo central, columna central, columnas centrales e imagen central. No tenemos mesa central aquí.
Entonces, ¿qué va a pasar cuando veamos esta página? Vamos a ver. Así que volveremos a la página de muestra en nuestra interfaz Faust. Y puede ver que todavía tenemos una tabla aquí con la fila 1 y la fila 2.
Esto se debe a que si el bloque aún no está definido en su proyecto Faust JS, haremos una alternativa inteligente y sensata al HTML renderizado. De esa manera, no verá contenido indefinido, nulo o simplemente sin contenido. Como mínimo, está recuperando el HTML renderizado original.
Con todo esto en mente, echemos un vistazo a lo que realmente se necesita para crear un bloque: cómo se ve realmente. Así que volveremos a VS Code aquí. Y elijamos la imagen principal, por ejemplo.
Así que puedes ver aquí, este es solo un componente tradicional de React. Lo llamamos imagen central. Y acepta accesorios, como cualquier otro componente de React.
Hay esencialmente dos piezas por bloque aquí. Así que tenemos el componente React real, que es la capa de presentación. Y luego obtenemos block.fragments, que son los datos que se necesitan para que funcione este bloque.
Entonces puede ver que aquí estamos creando un fragmento, un fragmento de imagen central en la imagen central. Y estamos obteniendo estos atributos, los atributos que necesitamos para representar este bloque. Como puede ver, obtenemos el texto alternativo, la fuente, el título, el nombre de la clase, el ancho, el alto, etc.
Y luego, lo que podemos hacer es aplicar esos atributos en nuestra lógica React real. Entonces, todos los campos que se solicitan aquí están disponibles en props. Entonces puede ver que salen props.attributes, que son los atributos que solicitamos aquí, atributos.alt, atributos.fuente, etc. Así que esta es una excelente manera de colocar todos los requisitos de datos para su bloque dentro del mismo archivo.
Esto es asegurarse de que solo solicite los datos que necesita y de que sus solicitudes sean agradables y eficaces. También tenemos algunas funciones auxiliares en este proyecto de ejemplo. Puede ver que hay un par aquí: obtenga estilos y obtenga accesorios de tamaño de imagen.
Básicamente, estos son simplemente tomar estos estilos de WordPress y combinarlos en un objeto de estilos real que React puede usar. Actualmente, los estilos son compatibles con los estilos en línea. También puede obtener hojas de estilo globales, pero actualmente estamos trabajando para brindar soporte para theme.json.
Así que Teresa hablará un poco sobre esto en nuestra hoja de ruta futura. Pero idealmente, llegará un punto en el que podamos obtener todos nuestros estilos y relleno, márgenes, etc. de theme.json y aplicarlo aquí en el front-end sin cabeza. Con todo eso en mente, comencemos una discusión técnica rápida con Teresa y yo para hablar sobre dónde estamos hoy con esta función y hacia dónde planeamos ir en el futuro.
TERESA GOBBLE: Gracias por esa demostración, Blake. Eso fue genial. Avancemos y entremos en algunos detalles técnicos ahora, y charlemos sobre cómo funciona esto. Entonces, el primero que tengo para ti es, ¿cuáles son los requisitos para usar los bloques de contenido de WPGraphQL?
BLAKE WILSON: Sí, sí. Gran pregunta Teresa. Entonces, el único requisito para usar el complemento es tener instalado WPGraphQL también. Obviamente, si desea que su sitio interactúe con Faust JS, puede instalar el paquete de bloques Faust JS, que ayudará a facilitar el renderizado y todas esas cosas buenas en el front-end sin cabeza. Pero para exponer realmente los datos del bloque, todo lo que necesita es WPGraphQL y el complemento WP GraphQL Content Blocks.
TERESA GOBBLE: Impresionante. ¿Cómo se recopilan también los datos del bloque?
BLAKE WILSON: Sí, así que todos los datos del bloque son recopilados por cualquier bloque en WordPress que use la función de tipo de bloque de registro. Entonces, casi cualquier bloque que esté usando que interactúe con esa función aparecerá en los bloques de contenido. Y lo mejor de eso es que se transmite con el archivo block.json y autodescribe y autodocumenta automáticamente todos esos campos. Así que tienes la documentación todo en uno.
TERESA GOBBLE: Ah, increíble. ¡Qué ahorro de tiempo! Otra cosa sobre la que me encantaría que hablaras un poco más es ¿qué sucede con un bloque sin soporte? ¿Qué sucede cuando se consulta un bloque no compatible?
BLAKE WILSON: Sí, esa es otra gran pregunta. Hay dos escenarios reales que pueden suceder aquí. Entonces, podría haber una instancia en la que digamos que tiene un bloque en los datos de su publicación que desde entonces se eliminó de WordPress.
Tal vez fue un bloqueo de terceros que se eliminó. Entonces, ese es un caso de un bloque no compatible que no es compatible tanto en el front-end de Faust como en el registro de WordPress. En ese caso, en realidad devolvemos un bloque a los bloques de contenido llamado bloque indefinido o bloque desconocido para que pueda escribirlo adecuadamente en su interfaz sin cabeza. Y luego, la segunda parte es si se admite un bloque en el registro de WordPress, pero aún no se admite en su front-end de Faust JS, en ese caso, lo que hacemos es recurrir al HTML renderizado. De esa manera, al menos, ha renderizado HTML que se muestra, no nulo, indefinido o cualquier valor por el estilo.
TERESA GOBBLE: Ah, increíble. Y esto en realidad me lleva a mi siguiente pregunta. En cuanto a los complementos de terceros en un sitio web desacoplado sin cabeza, ¿puede usar un complemento de terceros utilizando el complemento WPGraphQL Content Blocks? ¿Cómo funciona todo eso en conjunto?
BLAKE WILSON: Sí, sí. Entonces, para cualquier complemento de terceros, volviendo a la primera o segunda pregunta, siempre que interactúen con la función de tipo de bloque registrado en WordPress, ese bloque se expondrá automáticamente a los bloques de contenido de WPGraphQL. Entonces, mientras se procesan esos datos, puede crear el bloque en su interfaz Faust JS. Y lo bueno de eso es que digamos que tiene un bloque de terceros para un carrusel. Una vez que haya creado eso una vez en su front-end de Faust JS, puede reutilizarlo en otros proyectos en el futuro.
TERESA GOBBLE: Oh, genial. Ahí es donde entra la pieza de reutilización. Y con este complemento, en realidad puede cerrar parte de esa brecha con los complementos de terceros que no funcionan de forma inmediata con los sitios web desacoplados.
Además, si observa el chat ahora, en realidad tenemos un tutorial creado para ayudar a las personas a crear un bloque a partir de un complemento de terceros. Mira en el chat ahora, podrás verlo y darle un clic. Dale un marcador.
Entonces, ¿cómo manejas bloques dentro de bloques? Eso puede ser realmente complicado. ¿Puede hablarnos un poco de cómo se vería eso?
BLAKE WILSON: Claro, sí. Así que tenemos esta bandera o este parámetro cuando consulta bloques de contenido llamados planos. Y que o acepta un valor verdadero o falso. Entonces, cuando esto se proporcione como verdadero, en realidad obtendrá una matriz plana o una lista plana de todos los bloques en esa página, ya sea una columna, una imagen o un párrafo.
Tendrá una lista completa de todos los bloques consultados en esa página con dos propiedades adicionales. Uno es el ID del nodo. Esa es la identificación real de ese bloque en particular. Y luego también tendrá la identificación principal, que es la principal de ese bloque. Entonces, lo que puede hacer es reconstruir eso en una lista jerárquica real en su interfaz, prácticamente resolviendo el enigma del bloque interno como hemos visto antes en Gutenberg.
TERESA GOBBLE: Impresionante. Entonces, en realidad, hay una opción, al buscar bloques de contenido, que puede especificar para devolver una lista plana de bloques dentro de sus ID de padre e hijo apropiados.
BLAKE WILSON: Sí, sí, exactamente.
TERESA GOBBLE: Genial. De hecho, también tenemos otro tutorial aquí abajo en el chat, nuevamente, para que los bloques de contenido de WPGraphQL también echen un vistazo a esa función en particular. Así que quería hacerle otra pregunta sobre la pieza de estilo: diseñar con hojas de estilo globales, en línea, ¿cuál es el enfoque allí? ¿Cómo se maneja el estilo?
BLAKE WILSON: Sí, sí. Así que el estilo es probablemente uno de los mayores impulsos que estamos tratando de investigar en este momento. En el ejemplo que acabo de mostrar, se usan estilos en línea.
También se admiten estilos globales, hojas de estilos globales. Y creo que tocará esto a continuación en la hoja de ruta. Pero idealmente, también queremos admitir el soporte de theme.json, donde podemos obtener márgenes, rellenos, colores y toda esa buena información de theme.json, y luego aplicar eso. Así que estaremos trabajando en eso en nuestra próxima fase de desarrollo.
TERESA GOBBLE: Impresionante. Gracias por guiarnos a través de eso. Sé que mucha gente está realmente entusiasmada con eso. Entonces, ¿cómo impedimos que el editor use bloques que no son compatibles?
BLAKE WILSON: Sí, sí. Así que hay un complemento por ahí. Eso depende. Si está utilizando bloques de terceros, algunos de ellos ya tienen esta característica incorporada.
Pero si no, hay un complemento llamado visibilidad de bloque, que en realidad puede alternar bloques específicos desde la perspectiva del editor. Entonces, supongamos que tiene un bloque de carrusel que aún no se ha implementado en su sitio de Faust. Puede instalar la visibilidad de bloqueo y desmarcarla para que el editor no la use mientras aún no es compatible o está en desarrollo.
TERESA GOBBLE: Ah, increíble. Entonces, ¿la visibilidad del bloque del complemento puede alternar, ocultar y mostrar bloques específicos?
BLAKE WILSON: Sí, sí, exactamente. Entonces, de esa manera, tiene una cantidad limitada de bloques que ha admitido, tanto en su lado de WordPress como en su sitio sin cabeza para que los editores sepan, OK, podemos usar esto con certeza de que será compatible en el Interfaz.
TERESA GOBBLE: Oh, seguro que eso suena como una entrega más limpia. Está bien. Última pregunta para ti. ¿Estos bloques frontales corresponden al editor del editor?
BLAKE WILSON: Sí, gran llamada. Así que todavía no. Eso es algo en lo que vamos a estar trabajando en el futuro, pero por ahora, estos bloques son compatibles con el front-end sin cabeza.
Si tiene un bloque personalizado que ha creado en WordPress, si está utilizando el comando de creación de bloque NPX, aún deberá admitir esa vista en el lado de WordPress. Pero es algo en lo que estamos trabajando. Lo tenemos en nuestra hoja de ruta.
TERESA GOBBLE: Ah, increíble. DE ACUERDO. Gracias por hablar sobre esos puntos con nosotros, Blake. Eso ha sido realmente útil, y la demostración también.
Avancemos, cambiemos de marcha y hablemos un poco más sobre la hoja de ruta del proyecto. En realidad, tenemos cinco fases, dos de las cuales ya están completas: la fase 1 y la fase 2. En la fase 1, vimos una implementación de un método para deconstruir y luego reconstruir un bloque de manera eficiente.
Después de eso, pasamos a la fase 2, que se centró en una integración más estrecha de Faust con Gutenberg Blocks para garantizar que la gente tenga acceso completo a las diferentes utilidades y funciones auxiliares que se encuentran allí. En la siguiente fase en la que estamos ahora mismo, la fase 3, nos estamos enfocando en brindar compatibilidad con theme.json y bibliotecas de bloques reutilizables, como mencionó Blake durante nuestra discusión técnica.
Después de que hayamos hecho eso, sucederán las fases 4 y 5. La fase 4 se centra en mejorar la experiencia de desarrollo y edición existente, así como la fase 5, que se centra en respaldar el ecosistema más amplio más allá del núcleo de WordPress. Estamos muy entusiasmados con estas fases que se avecinan, y esperamos que se comunique con nosotros y eche un vistazo a nuestra publicación de blog para mantenerse actualizado sobre dónde está la hoja de ruta.
Puede ver un enlace en el chat a continuación a nuestras publicaciones de blog si echa un vistazo. Continúe y marque esos. Bueno, gracias a todos por unirse a nosotros en nuestra discusión sobre el puente React-Gutenberg. Quiero traer a Blake de vuelta a la pantalla aquí para que también pueda dar las gracias y darnos un poco más de información sobre dónde puede ir si tiene alguna pregunta pendiente después de esto.
BLAKE WILSON: Sí, gracias, Teresa, y gracias a todos los que se unieron a esta sesión hoy y vieron. Estamos muy emocionados de recibir algunos comentarios de la comunidad sobre esta característica para que todos ustedes comiencen a probarla.
Entonces, si te gusta, tenemos el proyecto de ejemplo en el enlace del chat. También tenemos un enlace en el chat para nuestro Discord sin cabeza, por lo que es solo un lugar donde usted y otros desarrolladores sin cabeza con ideas afines pueden unirse y conversar sobre las próximas funciones y lanzamientos en el espacio sin cabeza. Así que gracias a todos de nuevo. Nosotros realmente lo apreciamos.