【问题标题】:How to stop Chrome from turning relative links to absolute links on copy/paste?如何阻止 Chrome 在复制/粘贴时将相对链接转换为绝对链接?
【发布时间】:2016-07-29 15:42:26
【问题描述】:

我正在使用contenteditable="true"div 复制富文本并将其粘贴到Medium 草稿中。大多数格式都保留得很好,但由于某种原因,我不明白所有相对链接都转换为绝对链接。我不知道这发生在哪一步。我什至认为 Medium 可能正在监听“粘贴”事件。这将是最坏的情况,因为我几乎无法控制它。但如果是这样,他们如何访问我复制内容时所在页面的 URL?确实,在检查了其他浏览器之后,我得出结论是 Chrome 的错,而不是 Medium 的错。在 Safari 上它可以完美运行,在 Firefox 上它根本不起作用(但这是另一个问题的主题......)。

为了让事情更清楚,我试图通过编写一个基本相同的书签来模仿我在 Wordpress 博客上使用的 footnotes plugin 的行为。

这是一个演示页面,您可以在其中粘贴具有类似 wiki 语法的文本以用于内联引用,并将它们解析为适当的脚注:

https://rawgit.com/arielpontes/footnoter/master/index.html

在两种使用模式下([1] 复制/粘贴到演示页面或 [2] 使用小书签),生成的 html 都有正确的相对链接。但是,在 Chrome 上粘贴回 Medium 后,它们变得绝对,指向 rawgit.com 并破坏了功能。

但是,如果我从本地计算机而不是 rawgit.com 运行代码,则即使在 Chrome 上粘贴后,链接也会保持相对形式。

可能会发生什么?有什么办法可以解决吗?

【问题讨论】:

    标签: javascript jquery google-chrome copy-paste bookmarklet


    【解决方案1】:

    TL;DR - 负责粘贴内容的是将其放入剪贴板的程序。

    每次您将某些内容复制到剪贴板时,执行复制的应用程序都可以在其中放置多种数据类型,因此您paste 进入的程序将能够使用最适合它的那个。如果是浏览器 - 当您选择网页内容并复制到剪贴板时 - 浏览器将创建两种类型(html/plaintext/html),因此如果您将该内容粘贴到可以处理 html 的程序中 -您将粘贴的数据将是 html,但如果不是 - 该数据将是纯文本。

    基本上你有两个选择:

    1. 覆盖浏览器保存在剪贴板中的内容(这样 - 无论内容将被粘贴到哪里 - 它都会完全按照您想要的方式显示)
    2. 劫持粘贴事件,从剪贴板中获取数据,按照你想要的方式修改,然后自己放到编辑器中。

    $('#text').on('paste', function(e) {
      if ($('input[name=paste-type]:checked').val() == 'special') {
        e.preventDefault();
        if (window.getSelection) {
          sel = window.getSelection();
          if (sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
            node = document.createElement("p");
            text = 'Replacement text only for the paste'
            node.appendChild(document.createTextNode(text))
            range.insertNode(node);
          }
        }
      }
    });
    $(document).on('copy', function(e) {
      if ($('input[name=copy-type]:checked').val() == 'special') {
        e.preventDefault();
        if (window.getSelection) {
          sel = window.getSelection();
          if (sel.rangeCount) {
            range = sel.getRangeAt(0);
            nodes = range.cloneContents().childNodes
            content = ''
            contentPlain = ''
            for (var i = 0; i < nodes.length; i++) {
              node = nodes[i];
              contentPlain += node.textContent
              if (node.nodeType == 3) {
                content += node.textContent
              } else if (node.nodeType == 1) {
                content += node.outerHTML
              }
            }
          }
        } else {
          content = '<span style="color: red; background: yellow;">Replacement text only for the copy</span>';
        }
        e.originalEvent.clipboardData.setData('text/html', content);
        e.originalEvent.clipboardData.setData('text/plain', contentPlain);
      }
    });
    $('#btn1').click(function() {
      $('#ta1').val($('#text').html());
    });
    <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
    <div id="text" contenteditable="true" style="width: 400px; height :250px; border: 1px solid black;">Paste your text here...</div><br />
    <textarea id="ta1" style="width: 400px; height: 150px; border: 1px solid green;" disabled="disabled"></textarea><br />
    <button id="btn1">View HTML</button><br />
    <label for="reg"><input type="radio" name="paste-type" value="regular" id="reg" checked="checked" /> Regular Paste</label>
    <label for="special"><input type="radio" name="paste-type" value="special" id="special" /> Force my paste</label>
    <br /><br />
    <label for="copy-reg"><input type="radio" name="copy-type" value="regular" id="copy-reg" checked="checked" /> Regular Copy</label>
    <label for="copy-special"><input type="radio" name="copy-type" value="special" id="copy-special" /> Force my copy</label>
    <br /><br />
    <div style="width: 400px; height: 300px; border: 1px solid red;">
        <p>Nonumes molestiae <b>scripserit mei eu. In sea singulis evertitur</b>, verear inimicus delicatissimi ad eam. Eu eros scripserit cum, nam ferri ludus saperet te, ex sea nostro prompta inciderint. Est at causae .</p>
        <p>Quem feugait nam cu, sed <span style="background: red;">tantas meliore eu. Propriae efficiendi at</span> has, in usu nusquam noluisse, no nam natum verterem. Eu tation dignissim pro. Id eos wisi mollis commune</p>
        <p>Ea has quando blandit <a href="#a1">intellegebat, iusto</a> fabulas eos in, per consul suscipit inciderint cu. Ea veri possim nostrud vis. Id civibi. Ut duo posse <a href="#a2">graecis voluptatibus</a>, mea eu errem possim quaestio.</p>
    </div>

    在上面的示例中,我提供了您可以使用的选项(原始副本/粘贴和特殊副本/粘贴)。
    您可以在特殊副本的示例中看到 - 我构建了 html 字符串以从页面中的选择中放入剪贴板(基于 DOM 元素)。这样我就能够得到href 的确切值(无需将其更改为绝对路径)。

    为方便起见,jsfiddle 中的代码完全相同: https://jsfiddle.net/m0ad3uaa/

    【讨论】:

      【解决方案2】:

      问题出在客户端。浏览器使用绝对 URL 复制链接,这是为了防止在将链接粘贴到不同区域时出现问题。

      例如,如果我在http://site1.com 上单击一个看起来像&lt;a href="/myresource.jpg"&gt; 的链接,我将被定向到http://site1.com/myresource.jpg

      现在,如果您要将相同的标签复制到 http://site2.com,链接现在将指向 http://site2.com/myresource.jpg,它可能存在也可能不存在。

      这在大多数情况下是有道理的,就像您使用 Chrome 一样,您不太可能尝试复制网站、资产和所有内容。它还解决了&lt;img&gt; 标签指向不存在的资产的问题。

      然而,说到这一切,有可能以编程方式弄乱正在选择的内容。

      这里有一个很好的例子: http://bavotasan.com/2010/add-a-copyright-notice-to-copied-text/

      基本上,您只需将 document.oncopy 更改为 window.getSelection() 并删除您的域名的所有实例,确保链接是相对的。

      【讨论】:

      • 你能说出你的答案是如何准确地给出了这个问题上不存在的任何新信息吗?
      猜你喜欢
      • 2010-10-07
      • 2013-08-04
      • 2015-01-13
      • 2019-04-04
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多