Подтвердить что ты не робот

Как остановить Chrome от поворота относительных ссылок на абсолютные ссылки на копирование/вставку?

Я копирую богатый текст из div с помощью contenteditable="true" и вставляя его в проект Medium. Большая часть форматирования сохраняется в порядке, но по какой-то причине я не понимаю, что все относительные ссылки преобразуются в абсолютные. Я не знаю, на каком этапе это происходит. Я даже подумал, что Medium может слушать "вставку" событий. Это был бы худший сценарий, потому что у меня было бы очень мало контроля над ним. Но если да, то как они имеют доступ к URL-адресу страницы, на которой я был, когда я копировал содержимое? В самом деле, после проверки с другими браузерами, я пришел к выводу, что это ошибка Chrome, а не Medium. В Safari он отлично работает, на Firefox он вообще не работает (но это тема для другого вопроса...).

Чтобы сделать все более ясным, я пытаюсь подражать поведению плагина footnotes, который я использую в своем блоге Wordpress, написав букмарклет что делает практически то же самое.

Здесь представлена ​​демонстрационная страница, в которой вы можете вставлять текст с вики-подобным синтаксисом для встроенных ссылок и анализировать их в соответствующие сноски:

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

В обоих режимах использования ([1] копирование/вставка на демонстрационную страницу или [2] с помощью букмарклета), полученный html имеет соответствующие относительные ссылки. Однако после вставки обратно в Medium на Chrome они становятся абсолютными, указывая на rawgit.com и нарушая функциональность.

Если я запускаю код с локальной машины вместо rawgit.com, однако ссылки сохраняются в относительной форме после вставки даже в Chrome.

Что может быть? Есть ли способ исправить это?

4b9b3361

Ответ 1

TL; DR - тот, который отвечает за вставленный контент, - это программа, которая помещает его в буфер обмена.

Каждый раз, когда вы копируете что-то в буфер обмена, приложение, которое делает копию, может помещать туда несколько типов данных, поэтому программа, в которой вы paste, сможет использовать ту, которая лучше всего подходит для нее. В случае браузера - при выборе содержимого веб-страницы и копирования в буфер обмена - браузер создаст два типа (html/plain и text/html), поэтому, если вы вставляете этот контент в программу, которая может обрабатывать html - данные, которые вы вставляете, будут html, но если нет - эти данные будут простым текстом.

В принципе у вас есть два варианта:

  • Переопределить содержимое, которое браузер сохраняет в буфере обмена (таким образом - независимо от того, где будет вставлен контент - он будет выглядеть точно так, как вы хотите)
  • Убейте событие вставки, получите данные из буфера обмена, измените его так, как вы хотите, и поместите его в редактор самостоятельно.

$('#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>

Ответ 2

Проблема на стороне клиента. Браузеры копируют ссылки с абсолютными URL-адресами, это предотвращает возникновение проблем при вставке ссылок в разные области.

Например, если я нажму ссылку на http://site1.com, которая выглядит как <a href="/myresource.jpg">, я буду перенаправлен на http://site1.com/myresource.jpg.

Теперь, если вы должны были скопировать тот же тег на http://site2.com, ссылка теперь будет указывать на http://site2.com/myresource.jpg, которая может или не может существовать.

В большинстве случаев это имеет смысл, как если бы вы использовали Chrome, вряд ли вы захотите скопировать сайт, активы и все такое. Он также исправляет проблемы, в которых теги <img> указывают на те активы, которые не существуют.

Однако, говоря все это, можно программно испортить то, что выбрано.

Здесь отличный пример: http://bavotasan.com/2010/add-a-copyright-notice-to-copied-text/

По существу, вы просто захотите изменить document.oncopy, чтобы принять window.getSelection() и удалить все экземпляры своего имени домена, гарантируя, что ссылки будут относительными.