Preserving italics in pastes from webpages
Tired of losing italics in pastes from websites to your plain-text editor? For a while, I thought I needed to switch to a rich-text editor to handle these pastes, but that would be a pain for several reasons. A few days ago I realized I just needed to mutate the webpage by surrounding italic text with slashes. I would run a bookmarklet, then copy/paste. (Skip below for a working bookmarklet).
My first attempt at this used the :before and :after CSS pseudo-elements:
javascript:(function() { var newSS, styles='em:before, em:after, i:before, i:after { content: "/" }'; if(document.createStyleSheet) { document.createStyleSheet("javascript:'" + styles + "'"); } else { newSS = document.createElement('link'); newSS.rel = 'stylesheet'; newSS.href = 'data:text/css,' + escape(styles); document.getElementsByTagName("head")[0].appendChild(newSS); } })();
If you run the above (paste into your URL bar and hit enter), it looks like it works until you try to paste the text containing slashes; neither Chrome 10 or Firefox 4 will put the slashes in your clipboard. I threw out the simple clean non-working code and went for a terrible hack:
javascript:(function() { document.body.innerHTML = document.body.innerHTML. replace(/<em(\s.*?)?>([\s\S]+?)<\/em>/gi, "/<em$1>$2</em>/"). replace(/<i(\s.*?)?>([\s\S]+?)<\/i>/gi, "/<i$1>$2</i>/"). replace(/<span style="font-style: italic;">([\s\S]+?)<\/span>/gi, '/<span style="font-style: italic;">$1</span>/'). replace(/<strong(\s.*?)?>([\s\S]+?)<\/strong>/gi, "*<strong$1>$2</strong>*"). replace(/<b(\s.*?)?>([\s\S]+?)<\/b>/gi, "*<b$1>$2</b>*"); })();
This above replaces document.body.innerHTML with a new string where italics are surrounded with “/” and bold surrounded by “*”. This is terrible in several ways: it may break or re-run JavaScript code on the page, or somehow make you vulnerable to XSS (in a manner likely similar to the IE8 XSS “blocker”). Only while writing this post did I realize the security implications of the above. I decided to implement it using DOM manipulation (requires CSS3 selectors and querySelectorAll):
javascript:(function() { var wrapElements = function(selector, wrapperText) { var elements = document.querySelectorAll(selector); for(var i=0; i < elements.length; i++) { var surround = elements[i]; if(surround.parentNode) { surround.parentNode.insertBefore( document.createTextNode(wrapperText), surround); } surround.appendChild( document.createTextNode(wrapperText)); } }; var getStyleAttrVariations = function(elem, property, value) { return [ elem + '[style="' + property + ': ' + value + ';"]' ,elem + '[style="' + property + ': ' + value + '"]' ,elem + '[style="' + property + ':' + value + ';"]' ,elem + '[style="' + property + ':' + value + '"]' ]; }; wrapElements('em, i, span[class~="emphasis"], span[class~="italic"]', '/'); wrapElements(getStyleAttrVariations('span', 'font-style', 'italic').join(' ,'), '/'); wrapElements('strong, b, span[class~="bold"]', '*'); wrapElements(getStyleAttrVariations('span', 'font-weight', 'bold').join(' ,'), '*'); })();
If you don’t want to manually create a bookmark with the above code, you can drag this link to your toolbar or bookmarks:
I use a bookmark keyword in Firefox to activate it; keywords are not just for searches.
Here’s some bold and italic text so you know it’s working: bold, italic.