Mejora en recorte de correos electrónicos (sin recorte en bloques de código)

También he abierto un problema en GitHub al respecto, pero quería publicarlo aquí también en caso de que más gente esté atenta:

Creo que sería genial si la lógica de recorte de correos electrónicos pudiera mejorarse para evitar recortar dentro de bloques de código. Por ejemplo, en un correo electrónico que contenga:

```
# Esto no debería eliminarse
#
# O recortarse
# Es código
####
Código código código
```

Todo lo que está debajo del primer ‘#’ se recorta. Eso es un poco inconveniente, ya que muchas personas usan marcadores de comentarios para dividir secciones de su código, a veces incluso en cadenas multilínea para imprimir. También tiene la característica conveniente de que si las personas quieren copiar y pegar la salida del programa en un correo electrónico y esa salida incluye tales líneas, el correo electrónico no se recortará en ellas si la salida del programa está entre comillas. ¿Existe alguna posibilidad de que este sea un problema lo suficientemente común como para que alguien tenga un momento para ver si se podría mejorar? He llegado hasta la expresión regular donde ocurre la coincidencia, pero no estoy seguro de cuán complejo sería agregar una excepción para los bloques de código.

¡Gracias!

Ok, tuve que aprender un poco de Ruby, pero:

¡Se aceptan comentarios!

3 Me gusta

Para que estemos en la misma página, permíteme reformular tu problema para que hablemos de lo mismo :wink:

Quieres la capacidad de manejar correctamente los bloques de código cercados en las respuestas de correo electrónico, especialmente si incluyen el símbolo #, que a menudo se usa como delimitador (de firma) y, por lo tanto, se recorta.

Así que si enviaras la siguiente respuesta de correo electrónico

Aquí está mi parche

```
# Este es un comentario
####

respuesta = 42
```

¿Se ve bien?

Debería ser lo suficientemente “inteligente” como para reconocer que las líneas entre el ``` son código real y, por lo tanto, deben ser “ignoradas” del procesamiento normal.

Si ese es el caso, recomendaría una solución / enfoque diferente. Podría ser mejor izar todos los bloques de código en la función preprocess! e inyectarlos de nuevo después.

Los bloques de código cercados son algo difíciles de analizar correctamente usando una expresión regular, pero para una solución suficientemente buena, esto debería funcionar

def hoist_code_blocks(text)
  blocks = {}
  pattern = /^```\\w*$\\n.*?^```$/m
  
  text.gsub(pattern) do |block|
    token = SecureRandom.hex
    blocks[token] = block
    token
  end

  [text, blocks]
end

Este método reemplazará todos los bloques de código con un valor aleatorio y realizará un seguimiento del mapeo entre el valor aleatorio y el contenido del bloque en el hash blocks.

Puedes llamarlo así

text = "algún texto\n```ruby\ndef foo\nend\n```\nmás texto"
new_text, blocks = hoist_code_blocks(text)

Y luego puedes “restaurar” los bloques de código con el siguiente código

blocks.each { |token, block| new_text.gsub!(token, block) }

¡Gracias por la respuesta! Entendiste correctamente el problema que tengo, sí.

Pensé en hacer algo así también, y me alegra que se implemente si funciona y coincide lo más posible con el comportamiento del analizador en el navegador. Por ejemplo, en la interfaz del navegador se me permite espacio en blanco antes de mi declaración de idioma, y se me permite espacio en blanco después de mi cierre:

int x=42;<br>
```         (muchos espacios aquí)

Aún se renderiza correctamente como:
```                    c++
int x=42;

En el PR anterior intenté seguir las reglas que pude identificar en el analizador.

Las otras dos preguntas que haría sobre tu implementación son si esto realmente debería hacerse en preprocess!, para que los bloques también tengan que pasarse o ser retenidos por la clase EmailReplyTrimmer (y cuál sería preferible), y si podría haber un error ahí, porque el text que se devuelve allí es el mismo que el texto original, sin que se realicen sustituciones (¿aparentemente gsub devuelve un enumerador de las coincidencias, pero en realidad no estás haciendo el reemplazo aquí?).

En cualquier caso, me alegra que uses la prueba que se agregó en mi pull request anterior si prefieres agregar este código al analizador tú mismo, o si me informas sobre los problemas mencionados anteriormente, puedo crear un nuevo pull request. Captaste el problema perfectamente, y parece que tu solución está cerca, solo que no estoy seguro de cómo te gustaría que se finalizara.

¡Gracias!

Sí, se está volviendo complicado… Es factible, pero siempre habrá casos extremos en comparación con tener un analizador real.

También puedes tener más de 3 `, siendo 3 el mínimo :wink:

También puedes hacerlo en la función trim, justo después de la llamada a preprocess! y hacer el paso de “postprocesamiento” hacia el final.

Correcto, eso era principalmente pseudocódigo :sweat_smile:

Probablemente puedas usar gsub! o hacer text = text.gsub....

Ok, genial — he abierto una nueva PR aquí:

¡Gracias de nuevo!

3 Me gusta

También actualicé la versión en Discourse :up:

3 Me gusta

Este tema se cerró automáticamente después de 39 horas. Ya no se permiten nuevas respuestas.