2016-07-29 5 views
13

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

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

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

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

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

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

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

ответ

2

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

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

1

Проблема заключается на стороне клиента. Браузеры копируют ссылки с абсолютными 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() и удалить все экземпляры вашего доменного имени, гарантируя, что ссылки являются относительными вместо этого.

+0

Можете ли вы сказать, как именно ваш ответ дает любую новую информацию, которая не существует уже по этому вопросу? – Dekel