La propiedad CSS `white-space` de los datos del portapapeles no se respeta al pegar en el editor de texto enriquecido

Prioridad/Severidad:

Medio

Plataforma:

Sistema Operativo

  • Windows 11

Navegador

  • Google Chrome 139.0.7258.128

Discourse

028c90dd5e7a2799ea5b6e963f71fc0222681943

Descripción:

El texto copiado de algunas fuentes puede almacenarse en el portapapeles en un formato con estilo (text/html) además de texto plano (text/plain).

Cuando se pega texto en el editor, si hay un tipo de datos con estilo presente en el portapapeles, se utilizan esos datos en lugar del tipo de texto plano.

Por defecto, los espacios en blanco en el contenido HTML se reducen. Este comportamiento se puede controlar mediante la propiedad CSS white-space.

:bug: Al pegar en el editor cuando está en modo “editor de texto enriquecido”, no se respeta la propiedad CSS white-space de los datos del portapapeles. Esto da como resultado que los espacios en blanco siempre se reduzcan en el contenido pegado. En casos donde el contenido de origen tenía la propiedad white-space establecida en el valor pre, esto da como resultado que el contenido pegado sea difícil de leer e incorrecto en casos donde los espacios en blanco del contenido de origen tenían un significado técnico.

Pasos para reproducir:

  1. Cree un archivo HTML con el siguiente contenido:
    <html>
      <body>
        <span style="white-space: pre">foo
    bar
        </span>
      </body>
    </html>
    
  2. Abra el archivo en su navegador web.
    Observe que los espacios en blanco del contenido de la página no se reducen:
    foo
    bar
    
  3. Copie el contenido de la página web.
  4. Abra el editor de publicaciones.
  5. Ponga el editor en modo [“editor de texto enriquecido”].
  6. Pegue el contenido copiado.

:bug: En lugar de tener el mismo formato que el contenido copiado, los espacios en blanco del contenido pegado se redujeron:

foo bar

Contexto adicional:

Veo que ProseMirror soporta white-space: pre:


El fallo no ocurre al usar el editor en modo [“editor Markdown”].


El fallo no ocurre si el contenido se pega en un bloque de código en lugar de en el modo de editor normal. Es cierto que en muchos casos sería más apropiado colocar el contenido que usa algo como white-space: pre en un bloque de código. Sin embargo, es bastante común que los usuarios apliquen formato retroactivamente agregando el contenido al editor, seleccionando el contenido y luego usando la barra de herramientas del editor para aplicar el formato (en contraposición al enfoque alternativo de activar un bloque de código antes de agregar el contenido).


Encontré que esta es una herramienta útil para examinar los datos sin procesar del contenido del portapapeles:


Puedo reproducir el fallo en try.discourse.org en “modo seguro”.

Relacionado

2 Me gusta

¿Pusiste el editor de publicaciones en modo “editor de texto enriquecido” antes de pegar el contenido copiado de la página web?

El error persiste.

¿Estás seguro de que seguiste las instrucciones exactamente como estaban escritas?

Ten en cuenta que debes copiar el contenido que se renderiza desde ese HTML, de modo que el contenido del portapapeles se rellene con datos de tipo text/html:

<html>
<body>
<!--StartFragment--><span>foo
bar
    </span><!--EndFragment-->
</body>
</html>

No se trata de componer tu publicación usando marcado HTML.

Ah, buena observación. Tengo tendencia a leer las publicaciones demasiado rápido :sweat_smile:

1 me gusta

Gracias por informar @per1234, estamos revisando esto.

Entendemos el problema general aquí, queremos que sea lo más fácil posible para que las personas peguen ejemplos de código.

2 Me gusta

¿Qué esperarías de un portapapeles HTML así?

foo
bar

¿O, considerando que es una etiqueta span, dos líneas de código en línea con un salto de línea entre ellas?

foo
bar

¿O simplemente que respetemos los saltos de línea pero en un párrafo normal, con un salto de línea entre ellos?

foo
bar

¡Gracias!

No tengo muchos conocimientos sobre HTML, pero esperaría este resultado:

Por lo que puedo ver, así es como lo muestra el navegador Chrome.


Dicho esto, en el uso específico en el que encontré el problema, es cierto que el formato de bloque de código sería el más apropiado. Obtenemos este tipo de contenido del portapapeles haciendo clic en el botón “Copiar salida de la consola” en un IDE en línea llamado “Arduino Cloud Editor”:

Esto copia la salida producida por el compilador y otras herramientas al portapapeles. Este tipo de contenido que no es prosa se formatea mejor como un bloque de código.

Si se utiliza el siguiente procedimiento para compartir esa salida copiada en una publicación de foro:

  1. Poner el editor de publicaciones en modo “editor de texto enriquecido”.
  2. Pegar el contenido en el editor.
  3. Seleccionar el contenido pegado.
  4. Hacer clic en el icono </> en la barra de herramientas del editor.

La publicación termina con el siguiente formato:

/run/arduino/sketches/asdf/asdf.ino:1:2: error: #error foo  #error foo   ^~~~~

(nota que todo el contenido copiado está en una sola línea)

mientras que esperaríamos este formato de publicación:

/run/arduino/sketches/asdf/asdf.ino:1:2: error: #error foo
 #error foo
  ^~~~~

Sin embargo, esta preferencia por un bloque de código es específica de nuestro caso de uso particular. Puede ser que en otros casos de uso haya fuentes de contenido del portapapeles con una propiedad white-space: pre para las cuales un bloque de código no sería apropiado. E incluso para nuestro caso de uso, es razonable poner la responsabilidad de aplicar manualmente el formato de bloque de código en el usuario.

1 me gusta

Ya no, esto se ha corregido recientemente (puedes probarlo aquí).

En este caso, ¿sigue utilizando una etiqueta span en su salida del portapapeles text/html, o solo genera plain/text?

Si uso la herramienta “Clipboard Inspector” para comprobar qué datos hay en mi portapapeles después de hacer clic en el botón “Copy Console Output” en Arduino Cloud Editor, muestra que hay los siguientes datos de tipo “text/plain”:

/run/arduino/sketches/asdf/asdf.ino:1:2: error: #error foo
 #error foo
  ^~~~~

y los siguientes datos de tipo “text/html”:

<span style="color: rgb(0, 0, 0); font-family: &quot;Open Sans&quot;, &quot;Lucida Grande&quot;, lucida, verdana, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.16px; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">/run/arduino/sketches/asdf/asdf.ino:1:2: error: #error foo
 #error foo
  ^~~~~</span>

Espero que eso responda a tu pregunta. Estaré encantado de proporcionar información adicional si es necesario.

Esto debería arreglarse con FIX: [rich editor] convert newlines to hard breaks when parsed from HTML by renato · Pull Request #35518 · discourse/discourse · GitHub (aún no se ha fusionado, todavía está pendiente de revisión de código).

Mi primer intento fue convertirlo en un bloque de código, pero creo que sería demasiado precipitado y causaría algunos falsos positivos. En su lugar, respetamos los saltos de línea convirtiéndolos en saltos duros dentro del contexto en el que se pegó el HTML. (Gracias a la mejora de Marijn en prosemirror-model: When preserving whitespace, replace newlines with line break replacem… · ProseMirror/prosemirror-model@79e9f2b · GitHub)

Con las recientes mejoras en el botón de la barra de herramientas de código, los usuarios deberían poder seleccionar esta sección pegada con saltos duros y convertirla en un bloque de código, y los saltos de línea deberían conservarse.

2 Me gusta

Muchas gracias por la corrección @renato, ¡y por tomarte el tiempo de publicar una actualización aquí!

Las recientes correcciones de errores han llevado la funcionalidad del editor de texto enriquecido al punto en que puede servir para hacer que nuestro foro sea más accesible para usuarios menos técnicos que no están familiarizados con Markdown y no están motivados a aprenderlo.


Todavía hay un par de condiciones bajo las cuales los resultados no son los esperados, pero estas son cosas que no es razonable mitigar a través de la base de código de Discourse:

Corrupción debido a sintaxis de marcado incidental

Las publicaciones pueden corromperse en el caso de que haya contenido que se parezca incidentalmente a marcado. Esto se debe a la decisión intencional de admitir marcado en el editor de texto enriquecido.

Para nuestro caso de uso, donde se espera que aquellos que desean usar marcado utilicen el editor de Markdown, mientras que el editor de texto enriquecido está destinado solo para aquellos que no tienen interés en usar marcado, esta es una decisión muy desafortunada. Uno de los problemas más significativos que tenemos con los usuarios no técnicos que usan el editor de Markdown es la corrupción de publicaciones debido a marcado incidental y tenía grandes esperanzas de que el editor de texto enriquecido proporcionaría una solución para eso. Sin embargo, para el caso de uso en el que un foro solo proporcionará un editor de texto enriquecido, este diseño tiene perfecto sentido, ya que aún permite a los usuarios fluidos en Markdown componer publicaciones de manera eficiente.

Formato incorrecto debido a marcado inapropiado en el contenido del portapapeles

Tenemos un caso en el que el contenido de tipo “text/html” agregado al portapapeles al copiar desde una aplicación específica tiene marcado HTML inapropiado, lo que resulta en un formato incorrecto cuando el contenido se pega en el editor de texto enriquecido fuera de un bloque de código.

Por supuesto, este es un error en la aplicación y Discourse está actuando al 100% correctamente al formatear el contenido según lo indicado por el marcado.

1 me gusta

Muchas gracias @per1234

¿Puedes dar más detalles sobre ejemplos donde puede ocurrir corrupción? Todavía tenemos algunos casos extremos en torno a nodos que no sabemos cómo representar, pero intentamos prohibir el cambio al editor enriquecido en casos como este.

Con respecto al portapapeles, ciertamente queremos mejorar. Es un problema difícil, cualquier reproducción exacta aquí sería muy útil.

Claro. Me alegra si la información puede ser útil. Me gustaría reiterar mi declaración anterior:

Sin embargo, estaría feliz de estar equivocado al respecto :slightly_smiling_face:.

  1. Copia el siguiente código C++:
    #include <iostream>
    int main() {
      std::cout << __FILE__;
    }
    
  2. Abre el compositor de publicaciones.
  3. Pon el compositor en modo “editor de texto enriquecido”.
  4. Pega el contenido copiado en el compositor.

:slightly_frowning_face: El contenido está corrupto:

#include
int main() {
  std::cout << __FILE__;
}

(nota que el <iostream> ha sido suprimido por parecer una etiqueta HTML no admitida, y el __FILE__ ha sido tratado como marcado en negrita)

Esto podría verse como un error del usuario, ya que podría evitarse activando un bloque de código antes de pegar el contenido que no es prosa. Sin embargo, podríamos esperar que el flujo de trabajo alternativo de aplicar formato de bloque de código retroactivamente al contenido pegado sea igualmente válido (como lo es cuando se usa el editor de Markdown).

Equipo

  • Cualquier placa Arduino (ya sea oficial o de terceros)

Instrucciones

  1. Instala Arduino IDE 2.3.6, que se puede descargar de la página “Software” del sitio web de Arduino:
    https://www.arduino.cc/en/software/#ide-download-section
  2. Inicia Arduino IDE.
  3. Selecciona Archivo > Nuevo Sketch en los menús de Arduino IDE.
  4. Reemplaza el contenido del nuevo sketch con el siguiente código:
    void setup() {
      Serial.begin(9600);
      while (!Serial) {}  // Espera a que se abra el puerto serie.
      delay(500);         // Algunas placas requieren un retraso después de la inicialización del puerto serie.
      Serial.println("foo");
      Serial.println("bar");
    }
    void loop() {}
    
  5. Selecciona Herramientas > Monitor Serie en los menús de Arduino IDE para abrir la vista Monitor Serie, si aún no está abierta.
  6. Selecciona " 9600 " en el menú de velocidad en baudios en la vista Monitor Serie.
  7. Sube el sketch a tu placa Arduino.
  8. Selecciona la salida serie del campo en la vista Monitor Serie.
  9. Copia el contenido seleccionado.
  10. Abre el compositor de publicaciones de Discourse.
  11. Pon el compositor en modo “editor de texto enriquecido”.
  12. Pega el contenido copiado en el compositor.

:slightly_frowning_face: Cada línea del contenido copiado se coloca en un bloque de código separado:

foo

bar

Si inspeccionas el contenido del portapapeles, verás que, además del contenido esperado de tipo “text/plain”:

foo
bar

También contiene el siguiente contenido de tipo “text/html”:

<div style="color: rgb(78, 91, 97); font-family: monospace; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: nowrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; position: absolute; left: 0px; top: 0px; height: 18px; width: 1862px;"><pre style="margin: 0px;">foo
</pre></div><div style="color: rgb(78, 91, 97); font-family: monospace; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: nowrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; position: absolute; left: 0px; top: 18px; height: 18px; width: 1862px;"><pre style="margin: 0px;">bar</pre></div>

Dado que el Monitor Serie de Arduino IDE 2.x envuelve incorrectamente cada línea del contenido copiado de tipo “text/html” en etiquetas <pre>, la representación de cada línea del contenido pegado como un bloque de código separado por el editor de texto enriquecido de Discourse es correcta y esperada.

Al igual que con el otro problema que describí anteriormente, el formato inesperado se puede evitar activando de forma proactiva el formato de bloque de código antes de pegar el contenido.

2 Me gusta