【问题标题】:Why doesn't IE7 copy <pre><code> blocks to the clipboard correctly?为什么 IE7 不能正确地将 <pre><code> 块复制到剪贴板?
【发布时间】:2010-09-13 06:44:27
【问题描述】:

我们注意到 IE7 在 Stack Overflow 上发布的代码块有一种奇怪的行为。比如这个小代码块:

public PageSizer(string href, int index)
{
    HRef = href;
    PageIndex = index;
}

从IE7复制粘贴,结果如下:

公共 PageSizer(string href, int index){ HRef = href; PageIndex = 索引; }

不完全是我们的想法.. 底层的 HTML 源代码实际上看起来不错;如果您查看源代码,您会看到:

<pre><code>public PageSizer(string href, int index)
{
    HRef = href;
    PageIndex = index;
}
</code></pre>

那么我们做错了什么?为什么IE7不能合理的复制粘贴这段HTML?

更新:这与 &lt;pre&gt; &lt;code&gt; 在运行时通过 JavaScript 修改的块有关。 原生 HTML 可以正确呈现和复制;它是该 HTML 的 JavaScript 修改版本,其行为不符合预期。请注意,复制并粘贴到写字板或 Word 中是可行的,因为 IE 将不同的内容放入富文本剪贴板,而不是记事本从中获取数据的纯文本剪贴板。

【问题讨论】:

  • 哦,是的,这个 sux,我用的是 IE,不能从 sof 复制代码
  • IE8 和 IE9 仍然如此,除了使用其他浏览器之外没有别的办法吗?

标签: html internet-explorer


【解决方案1】:

这似乎是 IE6 的一个已知错误,而 prettify.js 有一个解决方法。具体来说,它将 BR 标记替换为 '\r\n'。

通过修改检查以允许 IE6 或 7,然后剪切和粘贴将在 IE7 中正常工作,但它将使用 换行符 后跟 空格。通过检查 IE7 并仅提供“\r”而不是“\r\n”,它将继续正确地剪切和粘贴和呈现。

将此代码添加到 prettify.js:

function _pr_isIE7() {
  var isIE7 = navigator && navigator.userAgent &&
       /\bMSIE 7\./.test(navigator.userAgent);
  _pr_isIE7 = function () { return isIE7; };
  return isIE7;
}

然后修改prettyPrint函数如下:

   function prettyPrint(opt_whenDone) {
     var isIE6 = _pr_isIE6();
+    var isIE7 = _pr_isIE7();

...

-        if (isIE6 && cs.tagName === 'PRE') {
+        if ((isIE6 || isIE7) && cs.tagName === 'PRE') {
          var lineBreaks = cs.getElementsByTagName('br');
+         var newline;
+         if (isIE6) {
+           newline = '\r\n';
+         } else {
+           newline = '\r';
+         }
          for (var j = lineBreaks.length; --j >= 0;) {
            var lineBreak = lineBreaks[j];
            lineBreak.parentNode.replaceChild(
-               document.createTextNode('\r\n'), lineBreak);
+               document.createTextNode(newline), lineBreak);
          }

你可以看到working example here

注意:我没有在 IE6 中测试过原来的解决方法,所以我猜它呈现时没有 IE7 中看到的 '\n' 引起的空间,否则修复是更简单。

【讨论】:

【解决方案2】:

问题来了:

您的代码着色脚本用
标记替换换行符。复制/粘贴时,IE7 显然不会将
标记转换为换行符,就像它在屏幕上所做的那样。

换句话说,你的代码变成了这样:

public PageSizer(string href, int index)&lt;br /&gt;{&lt;br /&gt;    HRef = href;&lt;br /&gt;    PageIndex = index;&lt;br /&gt;    }

但你希望它变成这样:


public PageSizer(string href, int index)<br />
{<br />
    HRef = href;<br />
    PageIndex = index;<br />
}<br />

在 Google Code 上最新版本的 prettify.js 中,负责的行是第 1001 行(recombinineTagsAndDecorations 的一部分):


html.push(htmlChunk.replace(newlineRe, '<br />'));

根据 cmets 编辑:
对于 IE7,这行应该改成这样:


html.push(htmlChunk.replace(newlineRe, '\n'));

(假设 newlineRe 是占位符)。

此修复也适用于 Chrome 和 FFX3...我不确定哪些(如果有)浏览器需要
标签。

更新: 更多信息在我的第二个回复中:
Why doesn't IE7 copy <pre><code> blocks to the clipboard correctly?

【讨论】:

  • 那么为什么粘贴到 MS Word 中看起来不错呢?
  • 可能是因为 Word 粘贴为格式化的 HTML,或者是因为您之前提到的 CR + LF 问题。
  • 做了一些测试 -- 选择性粘贴 --> 无格式文本仍然将所有内容粘贴到 Word 的一行中。富文本编辑器似乎作为换行符提供
    s,纯文本被提供源中存在的任何空格,而
    s 被忽略。我的解决方案应该仍然可以解决这个错误。
  • 我不认为这个解决方案会起作用:因为美化代码吸收了 CODE 标签,但留下了 PRE 标签,它会以双倍间距呈现。
  • 嗯,双倍行距是对的。在 IE7、Chrome 和 FFX3 中,即使没有
    标签,也会显示换行符。我想知道哪些浏览器需要它们?如果不出意外,可以检测到 IE7 并在其他浏览器获取
    标签时提供换行符。
【解决方案3】:

这看起来像 IE 中的一个错误,PRECODE 中的 BR 标记没有被转换为纯文本副本中的换行符缓冲。富文本复制缓冲区很好,因此对于 wordpad 等应用程序,粘贴工作正常。

为代码着色的美化脚本会删除 all 空格,并用 HTML 标记替换空格和换行符。生成的代码如下所示:

code<br>  code<br>  code<br>code

PRECODE 标签默认以 {whitespace: pre} 的 CSS 样式呈现.在这种情况下,IE 无法将 BR 标记转换为换行符。它适用于您的原始 HTML,因为 IE 会成功地将实际换行符转换为换行符。

为了修复它,您有 3 个选项。 (我假设您想要漂亮的 HTML 能够在客户端启用和不启用 javascript 的情况下正常工作):

  1. 您可以将代码放在一个普通的 div 中,并使用 CSS 使用 {whitespace: pre} 来呈现它。这是一个简单的解决方案,虽然可能不会让 HTML 标记纯粹主义者满意。

  2. 您可以拥有两份代码,一份使用正确的 PRE / CODE 标签,另一份在普通 div 中。在您的 CSS 中,您隐藏了普通的 div。使用 javascript 美化普通 div 并隐藏 pre/code 版本。

  3. 修改美化脚本以识别它作用于 PRECODE 元素,并且不替换该事件中的空格。


注意事项:

  • 重要的不是源代码中的 HTML,而是运行美化脚本后生成的 HTML。

  • 即使使用 CSS 将 PRE 的空白模式更改为 普通,此错误仍然存​​在。

【讨论】:

  • 这不是 CR + LF 问题。我将文本粘贴到十六进制编辑器中,并且不存在 CR/LF 字符。 Word、写字板和记事本之间的差异是因为 IE7 将您复制到剪贴板的所有内容都保存了三个副本:纯文本、HTML 和 RTF。
  • HTML 格式是正确的,因为它包含实际使用的 HTML(这没有错)。 RTF 可能源自 HTML 版本,使用的算法与用于在屏幕上显示信息的算法相同。
  • 带有 white-space:pre 的 div 仍然存在与 PRE/CODE 块相同的问题(
    标签在纯文本剪贴板中被忽略),并且仍然需要 prettify.js修改。
  • 你确定吗?由于我没有在工作中安装 Windows,所以我不能测试它,因为我没有在工作中安装 Windows,但是,周五我确实尝试将 pre 和 code 设置为 white-space:normal,但我仍然遇到了这个错误。
  • 我有一个针对这个问题的测试文档,我可以用它来玩弄 HTML。
    ...
    行为与
     ... 
    至少在复制/粘贴方面相同。当然,在实际文档中 ... 由多行加上几个
    s.
    组成
【解决方案4】:

这个网站已经解决了这个问题:http://www.developerfusion.com/tools/convert/csharp-to-vb/

我建议将“复制到剪贴板”按钮作为代码显示框的一部分。 此按钮会将显示信息的版本复制为纯文本。 纯文本可以存储为内部页面属性。

【讨论】:

    【解决方案5】:

    坏消息:建议的修复都不起作用。在第 1000 行左右修改 prettify.js

    html.push(htmlChunk.replace(newlineRe, '\n'));
    

    这会导致其他浏览器出现双倍行距,仍然并不能解决 IE7 复制到记事本的问题!因此,即使我选择性地检测到 IE7,这个“修复”也无法修复任何问题。

    我想这可能只是 IE7 中的一个错误,它与 JavaScript 重建 &lt;pre&gt; 元素有关——无论我在那里放了多少 \n 换行符,粘贴到记事本上都没有任何改变行为。

    【讨论】:

    • 如果您使用“\r”而不是“\n”,这可能会起作用。我提供了一个似乎可行的更复杂的答案。
    • 你确定你的preffify文件的缓存副本被替换了吗?
    【解决方案6】:

    @杰夫阿特伍德 这是正确的想法,但实施仍然需要工作。我想我的航空代码只是没有削减它:)

    我怀疑我之前提到的修复不起作用,因为 prettify 在调用 ~1000 行之后对文本进行了一些额外的处理。

    试图从添加到页面时向后跟踪内容,我在第 1227 行附近遇到了这条评论:

    
    // Replace <br>s with line-feeds so that copying and pasting works
    // on IE 6.
    // Doing this on other browsers breaks lots of stuff since \r\n is
    // treated as two newlines on Firefox, and doing this also slows
    // down rendering.
    

    当我从代码中删除 isIE6 条件时,它主要在 IE7(顶部和底部有一个额外的换行符)和 Firefox 3... FFX 版本。

    至少,IE7 似乎需要\r\n,而不仅仅是\n。确切地弄清楚哪些浏览器可以使用比我目前手头更广泛的测试设置。

    无论如何,为 IE7 插入 \r\n 似乎基本上是需要发生的事情。我会继续探索美化,看看我是否可以进一步缩小范围。

    更新: IE7 似乎从分配给 innerHTML 属性的字符串中去除换行符(\r 或 \n)。看起来它们需要重新添加到第 1227 行附近。

    正确的解决方案可能是在第 1000 行周围插入一个占位符标记,然后在第 1227 行周围替换它。

    【讨论】:

      【解决方案7】:

      删除内部&lt;code&gt;。 IE 的复制/粘贴行为可以将其视为内联标记而忘记可见的空白。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-13
        • 2010-11-07
        • 2010-12-08
        相关资源
        最近更新 更多