Strip external formatting but keep indentation and carriage returns on element input

Tags: , ,



I’m using the following:

<style>
        pre {
            outline:none;
            font-family : monospace;
            white-space : pre;
            background-color : rgb(19, 22, 27);
            color            : #98d8e7;    
        }
        </style>
        <body>  
            <pre contenteditible="true"></pre>
        </body>

In Chrome, I’m given the option to “Paste” (undesired result) or “Paste and match style” (desired result), but in other browsers only “Paste” is offered.

A regular “Paste” keeps the original content formatting that I don’t want, like text colors and background colors. This is creating an undesirable result for my use case.

What I want to do is always force a paste to match the style of the <pre> element.

One idea that I had is to intercept the pasted text, pass it to an invisible textarea element then get that value. But that seems like it’s extra work for something that (in my mind at least) should be very simple. But I’m not sure how to accomplish it.

I’m open to javascript or css solutions. Anything, really.

Answer

Apologies if I’m stating the obvious here—I get that this doesn’t fully solve your problem—but you might be able to do something with the paste event where you grab the paste event’s data as text and set the element’s innerHTML to that.

This approach may not preserve white space in the way you intend. The skeletal implementation below replaces the contents of the entire element, but you could do something with getSelection to fix that if you went this route:

function onPaste (e) {
  e.preventDefault(); // stop the paste
  const t = e.clipboardData.getData("text"); // grab the pasted content as plain text
  e.target.innerHTML = t; // set the element's innerHTML to the plain text
}

const p = document.getElementById('test');
p.addEventListener('paste', onPaste);
pre {
  min-height: 200px;
  outline: none;
  font-family: monospace;
  white-space: pre;
  background-color: rgb(19, 22, 27);
  color: #98d8e7;
}
<pre id="test" contenteditable></pre>

Another similar possibility would be to let the paste go through, then immediately grab the element’s contents and strip out all the formatting. This seems like a more daunting approach but it would give you the ability to do a more surgical cleanup.

function onPaste (e) {
  // setTimeout to wait for the paste to complete
  setTimeout(() => {
    // do something with p.innerHTML or p.innerText;
    console.log(e.target.innerHTML);
  }, 0);
}


Source: stackoverflow