电子邮件裁剪改进(代码块中不进行裁剪)

我也就此问题开了个 GitHub issue,但同时也想在这里发帖,以防更多人关注:

我认为如果能改进电子邮件修剪逻辑,避免在代码块内进行修剪,那就太好了。例如,在包含以下内容的电子邮件中:

```
# This should not be deleted
#
# Or trimmed
# It is code
####
Code code code
```

第一行 ‘#’ 下面的所有内容都会被修剪。这有点不方便,因为很多人使用注释标记来分隔代码的各个部分,有时甚至在多行字符串中用于打印。它还有一个方便的功能,即如果有人想将程序输出复制并粘贴到电子邮件中,并且该输出包含此类行,则电子邮件不会在这些行处被修剪,前提是程序输出被包含在反引号中。这种情况是否足够普遍,以至于有人可以花点时间看看是否可以改进?我已经看到了匹配发生的正则表达式,但不确定为代码块添加例外会有多复杂。

谢谢!

好的,我学了一点 Ruby,但是:

欢迎讨论!

3 个赞

为了确保我们理解一致,我将重新表述您的问题,以便我们谈论的是同一件事;)

您希望能够正确处理电子邮件回复中的围栏代码块,特别是当它们包含“#”符号时,“#”符号通常用作(签名)分隔符,因此会被修剪掉。

因此,如果您要发送以下电子邮件回复

这是我的补丁

```
# 这是些注释
####

answer = 42
```

看起来好吗?

它应该足够“智能”,能够识别```之间的行是实际代码,因此应该被“忽略”常规处理。

如果确实如此,我建议采用不同的解决方案/方法。最好在 preprocess! 函数中提升所有代码块,然后再注入它们。

使用正则表达式正确解析围栏代码块有些困难,但对于一个足够好的解决方案,这应该可行

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

此方法将用随机值替换所有代码块,并在 blocks 哈希中跟踪随机值与块内容之间的映射。

您可以这样调用它

text = "some text\n```ruby\ndef foo\nend\n```\nmore text"
new_text, blocks = hoist_code_blocks(text)

然后您可以使用以下代码“恢复”代码块

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

感谢您的回复!您准确地理解了我遇到的问题,是的。

我也考虑过做类似的事情,如果它能正常工作并且尽可能接近浏览器解析器的行为,我很乐意实现它。例如,在浏览器界面中,我可以在语言声明之前和结束标记之后添加空格:

``` (此处有许多空格) c++
int x=42;
``` (此处有许多空格)

仍然正确地渲染为:

int x=42;

在上面的 PR 中,我试图遵循我在解析器中能够识别的规则。

关于您的实现,我还会问另外两个问题:这是否应该在 preprocess! 中完成,以便块也必须传递或由 EmailReplyTrimmer 类持有(哪种方式更可取),以及那里是否存在错误,因为返回的 text 与原始文本相同,没有任何替换(似乎 gsub 返回匹配项的枚举器,但您实际上并没有在这里进行替换吗?)。

无论如何,如果您愿意将此代码添加到解析器中,或者如果您告知我上述几个问题,我可以创建一个新的 pull request。您绝对正确地抓住了问题,并且您的解决方案看起来很接近,我只是不确定您希望如何完成它。

谢谢!

是的,这开始变得复杂了……这是可以做到的,但与使用真正的解析器相比,总会有一些边缘情况。

你也可以使用超过3个反引号,3个是最小值 :wink:

你也可以在 trim 函数中完成,就在 preprocess! 调用之后,并在最后进行“后处理”步骤。

是的,那大部分是伪代码 :sweat_smile:
你可能需要使用 gsub! 或者 text = text.gsub...

好的,太棒了——我在这里开了一个新的 PR:

再次感谢!

3 个赞

Bumped the version in Discourse as well :up:

3 个赞

此主题已在 39 小时后自动关闭。不再允许回复。