3

In contenteditable regions, if you paste an element with a URL attribute, in some browsers it converts the URL from relative to absolute.

I've read through some bug reports that claim it's "fixed" in the latest release, but it's not.

I threw together this fiddle to demonstrate: Hurray for Demos!

It's there, it's ugly, and I'm wondering what is the best way to fix it.

  1. The 1st idea that comes to mind is onpaste, find all anchors in the current node and parse it with regex. Not ideal I suppose, but it might be effective.

  2. ???

  3. ???

I really wish they'd just leave things alone and not create so many browser related issues with contenteditable, but I guess that would make it too easy.

Any thoughts on the best way to address this?

Community
  • 1
  • 1
Casey Dwayne
  • 2,142
  • 1
  • 17
  • 32

2 Answers2

1

CKEditor, before letting browser break the data, copies all src, name and href attributes to data-cke-saved-src|href attributes. Unfortunately, since data is a string, it has to be done by regexp. You can find the code here: /core/htmldataprocessor.js#L772-L783.

var protectElementRegex = /<(a|area|img|input|source)\b([^>]*)>/gi,
    // Be greedy while looking for protected attributes. This will let us avoid an unfortunate
    // situation when "nested attributes", which may appear valid, are also protected.
    // I.e. if we consider the following HTML:
    //
    //  <img data-x="&lt;a href=&quot;X&quot;" />
    //
    // then the "non-greedy match" returns:
    //
    //  'href' => '&quot;X&quot;' // It's wrong! Href is not an attribute of <img>.
    //
    // while greedy match returns:
    //
    //  'data-x' => '&lt;a href=&quot;X&quot;'
    //
    // which, can be easily filtered out (#11508).
    protectAttributeRegex = /([\w-]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,
    protectAttributeNameRegex = /^(href|src|name)$/i;

function protectAttributes( html ) {
    return html.replace( protectElementRegex, function( element, tag, attributes ) {
        return '<' + tag + attributes.replace( protectAttributeRegex, function( fullAttr, attrName ) {
            // Avoid corrupting the inline event attributes (#7243).
            // We should not rewrite the existed protected attributes, e.g. clipboard content from editor. (#5218)
            if ( protectAttributeNameRegex.test( attrName ) && attributes.indexOf( 'data-cke-saved-' + attrName ) == -1 )
                return ' data-cke-saved-' + fullAttr + ' data-cke-' + CKEDITOR.rnd + '-' + fullAttr;

            return fullAttr;
        } ) + '>';
    } );
}

Then, while processing HTML taken from editable element, data-cke-saved-* attributes override the original ones.

Reinmar
  • 21,729
  • 4
  • 67
  • 78
  • Eesh, that's quite a work-around. Interesting approach though. I built a simple function that just finds the base url and removes it. Guess my approach needs work since like you say, image use `src` not `href`. Thanks for the input! – Casey Dwayne Feb 12 '14 at 17:27
  • Sometimes I've got a feeling that everything CKEditor does is working-around browser bugs, quirks and inconsistencies ;). – Reinmar Feb 12 '14 at 18:23
  • - and an extensive list it is. I reference your editor and TinyMCE as well, but there's just so much *extra* in there that it turns me away (same goes for nearly every 3rd party software/plugin). Developing from scratch.. it's been educational to say the least :) – Casey Dwayne Feb 12 '14 at 19:29
  • Khem... :D Working on CKEditor for more two years I indeed learnt a loooot. One of the things is that I should never try to write from scratch anything production-ready with contenteditable... But, good luck! :) – Reinmar Feb 12 '14 at 21:54
0

This looks like a browser bug that's not specific to contenteditable: https://bugzilla.mozilla.org/show_bug.cgi?id=805359

That issue was opened 10 years ago and last updated 6 years ago. Yet it's still open.

You can see the bug here on StackOverflow. Inspecting any SO link shows that the href value is a relative URL. Copying it and pasting it as HTML has the relative link rewritten into an absolute URL.

Example:

enter image description here

enter image description here

Isaac Gregson
  • 1,999
  • 1
  • 21
  • 31