This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021

Typora is one of the software I use a lot. It is very comfortable to write MarkDown and has a very good use experience:

  • Real-time preview

  • Custom picture upload service

  • Document conversion

  • Theme customization

The cause of

But one really interesting thing I’ve encountered is that when I copy Typora content and paste it into a text editor, I get MarkDown content; When copied to a rich text editor, you can render rich text:

Copy to VS Code:

Copy to other rich text editors:

I’m curious why the two different results appear, Typora is supposed to have been developed using Electron(or similar technology) and I tried using the Clipboard API to test it out:

// Why use setTimeout: I tested it on the Chrome console,
// ClipBoard relies on the page, so I need to set the 1s delay so I can click the page focus
setTimeout(async() = > {const clipboardItems = await navigator.clipboard.read();
    console.log(clipboardItems)
},1000)

Copy the code

Then you see that there are two different types of content in the clipboard: plain text/plain and rich text/ HTML. So different content receivers select different content as data, text editors get plain text, and rich text editors get rich text.

Let’s take a look at the details:

setTimeout(async() = > {const clipboardItems = await navigator.clipboard.read();
    console.log(clipboardItems)
    for (const clipboardItem of clipboardItems) {
      for (const type of clipboardItem.types) {
        const contentBlob = await clipboardItem.getType(type)
        const text = await contentBlob.text()
        console.log(text)
      }
    }
},1000)

Copy the code

Try Clipboard with data:

setTimeout(async() = > {await navigator.clipboard.write([
      new ClipboardItem({
        ["text/plain"] :new Blob(['# plain text and rich text '] and {type:'text/plain'}),"text/html"] :new Blob(['

'
] and {type:'text/html'})})]); },1000) Copy the code

Several rich text editors have been tried with the results (specific implementations may vary from rich text editor to rich text editor) :

  • If only plain text exists (preserving only the plain text portion of the previous code), the plain text content of the clipboard is read

  • If plain and rich text exist, the rich text content in the clipboard is read

So did Typora help us achieve this effect?

Let’s take a look at the default behavior for copying text from a web page. Open a web page, copy text from a web page, and then try it out using the code I just described and see what the clipboard reads.

As you can see, when copying rich text, Chrome’s ClipBoard API produces two results, one in plain text format and one in rich text format.

The difference is that when we copy in Typora, we get plain text and rich text in Markdown format, and Typora does it for us.

Listen for replication and write to the clipboard

We can use htmlElement. onCopy to do this:

Open any web page and switch to the console:

document.body.oncopy = function(e){
   console.log(e)
    var text = e.clipboardData.getData("text");
    console.log(text)
}

Copy the code

Copy the contents of the page and we can see the printed result:

Data will be in clipboardData originally, but I tried to get the content, but I did not get the content, look at the API, you need to set the data in the copy event through setData, getData in paste time to get the data. The Selection API is used to retrieve the selected content.

document.addEventListener('copy'.function(e){
    e.preventDefault(); // To prevent overwriting the data we sift in
    const selectionObj = window.getSelection()
    const rangeObj = selectionObj.getRangeAt(0)
    const fragment = rangeObj.cloneContents() // Get the document fragment contained in Range
    const wrapper = document.createElement('div')
    wrapper.append(fragment)
    e.clipboardData.setData('text/plain', wrapper.innerText + 'Extra text');
    e.clipboardData.setData('text/html', wrapper.innerHTML+ '

Additional text

'
); }); Copy the code

Or use clipboard.write to write:

document.body.oncopy = function(e){
    e.preventDefault();
    const selectionObj = window.getSelection()
    const rangeObj = selectionObj.getRangeAt(0)
    const fragment = rangeObj.cloneContents() // Get the document fragment contained in Range
    const wrapper = document.createElement('div')
    wrapper.append(fragment)
    navigator.clipboard.write([
      new ClipboardItem({
        ["text/plain"] :new Blob([wrapper.innerText,'Extra text'] and {type:'text/plain'}),"text/html"] :new Blob([wrapper.innerHTML,'

Additional rich text

'
] and {type:'text/html'}})})])Copy the code

Listening for copying can also be used to add copyright information, such as the extra information in the code above that appears in the copied text.

Document. ExecCommand is also available for copying and pasting content, but it is currently a deprecated API and is not recommended

Welcome to follow the wechat public account “Hunchaofront-end”

Reference Documents:

ClipboardItem

Clipboard-write

element.oncopy

Selection

Range