์ผ€์ด์Šค ce-0301-safari-paste-link-url-only-en-ko ยท ์‹œ๋‚˜๋ฆฌ์˜ค scenario-paste-link-behavior

Pasting link from right-click context menu pastes only URL in Safari

OS: macOS 13-14 ๊ธฐ๊ธฐ: Desktop or Laptop Any ๋ธŒ๋ผ์šฐ์ €: Safari 16+ ํ‚ค๋ณด๋“œ: US QWERTY ์ดˆ์•ˆ
pastelinksafariclipboardurl

Phenomenon

In Safari, copying a link via right-click and then pasting it into a contenteditable area may result in only the URL being pasted, without the linkโ€™s title or other associated HTML. This behavior contrasts with Chrome and Firefox, where both the linkโ€™s title and URL are typically preserved.

Reproduction example

  1. Open Safari browser on macOS.
  2. Right-click on a link on any webpage and select โ€œCopy Linkโ€.
  3. Focus a contenteditable element.
  4. Paste the link (Cmd+V).
  5. Observe that only the URL is pasted as plain text.

Observed behavior

  • Only the URL is pasted as plain text
  • Link title is lost
  • No HTML link structure is created
  • Link formatting is not preserved

Expected behavior

  • Link should be pasted with both title and URL
  • HTML <a> element should be created with proper href attribute
  • Link formatting should be preserved
  • Behavior should be consistent with other browsers

Impact

  • Loss of context: Link titles provide important context that is lost
  • Manual work: Users must manually recreate links with titles
  • Inconsistent behavior: Different from other browsers, causing confusion

Browser Comparison

  • Safari: Only URL is pasted (this issue)
  • Chrome: Link with title and URL is pasted correctly
  • Firefox: Link with title and URL is pasted correctly
  • Edge: Link with title and URL is pasted correctly

Notes and possible direction for workarounds

  • Clipboard API: Use Clipboard API to read link data and manually create link elements
  • Paste event handling: Intercept paste events and reconstruct links from clipboard data
  • Fallback detection: Detect plain URL pastes and convert them to links

Code example

const editor = document.querySelector('div[contenteditable]');

editor.addEventListener('paste', async (e) => {
  e.preventDefault();
  
  const clipboardData = e.clipboardData || window.clipboardData;
  const pastedText = clipboardData.getData('text/plain');
  
  // Check if pasted text is a URL
  const urlPattern = /^https?:\/\/.+/;
  if (urlPattern.test(pastedText.trim())) {
    // Try to get link title from clipboard
    let linkTitle = pastedText;
    
    // Try to read HTML from clipboard
    try {
      const htmlData = clipboardData.getData('text/html');
      if (htmlData) {
        const parser = new DOMParser();
        const doc = parser.parseFromString(htmlData, 'text/html');
        const link = doc.querySelector('a');
        if (link) {
          linkTitle = link.textContent || link.href;
        }
      }
    } catch (err) {
      // Fallback to URL if HTML parsing fails
    }
    
    // Create link element
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      range.deleteContents();
      
      const link = document.createElement('a');
      link.href = pastedText.trim();
      link.textContent = linkTitle;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      
      range.insertNode(link);
      range.collapse(false);
      
      selection.removeAllRanges();
      selection.addRange(range);
    }
  } else {
    // Not a URL, paste as normal text
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      range.deleteContents();
      range.insertNode(document.createTextNode(pastedText));
      range.collapse(false);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  }
});

Playground for this case

Use the reported environment as a reference and record what happens in your environment while interacting with the editable area.

Reported environment
OS: macOS 13-14
Device: Desktop or Laptop Any
Browser: Safari 16+
Keyboard: US QWERTY
Your environment
Sample HTML:
Event log
Use this log together with the case description when filing or updating an issue.
0 events
Interact with the editable area to see events here.