Copy and paste original TeX using JavaScript

30 views
Skip to first unread message

Will Y

unread,
Dec 20, 2024, 2:12:04 AM12/20/24
to MathJax Users
Hello,

I'm writing a Chrome extension that will run on a website I don't own. The aim is to copy and paste entire sections so that I may be able to store them in my notes.

Basically, I'm trying to replicate the "Copy to Clipboard" functionality from the popup (see screenshot), but in client-side Javascript, so that I may automate it and add extra text in the copied content.

Is there a way to do this? Another way of thinking about it is like doing the reverse direction -- given a MathJax HTML block, I want to retrieve the original TeX.

Thank you,
Will


Screenshot 2024-12-20 020955.png

Davide Cervone

unread,
Dec 22, 2024, 4:05:34 PM12/22/24
to mathja...@googlegroups.com
Will:

Here is a function that will copy the current selection to the clipboard (as both plain text and rich text), but replacing the typeset math by its original TeX code in MathJax v3:

function copyOriginalSource() {
  const selection = document.getSelection();
  const nodes = document.createElement('div');
  for (let i = 0; i < selection.rangeCount; i++) {
    nodes.append(selection.getRangeAt(i).cloneContents());
  }
  const math = Array.from(nodes.querySelectorAll('mjx-container'));
  if (math.length) {
    let i = 0;
    let id = math[i].getAttribute('ctxtmenu_counter');
    for (const item of MathJax.startup.document.math) {
      if (item.typesetRoot?.getAttribute('ctxtmenu_counter') === id) {
        const tex = item.start.delim + item.math + item.end.delim;
        const mjx = nodes.querySelector('mjx-container');
        mjx.replaceWith(document.createTextNode(tex));
        id = math[++i]?.getAttribute('ctxtmenu_counter');
      }
    }
  }
  Promise.all([
    new Blob([nodes.textContent], {type: 'text/plain'}),
    new Blob([nodes.innerHTML], {type: 'text/html'})
  ]).then(([text, html]) => {
    const data = new ClipboardItem({
      [text.type]: text,
      [html.type]: html
    });
    navigator.clipboard.write([data]);
  });
}

There are a couple of caveats:

First, it doesn't properly handle the "escaped" output.  That is, if the original source had \$ in order to get an explicit dollar sign rather than an in-line math delimiter, then the backslash is not put back in place during the copy.  If you need that, it would take a bit more work.

Second, this only works for TeX or AsciiMath input, not MathML input, which would need to be handled more carefully.  If you need that, the code would need to check for that and handle it differently.  It can be done, but I didn't want to complicate the situation unnecessarily.

Third, this function has to be called from within an event handler like a button click or a keypress (or a menu selection).  You can probably attach an event listener to the "copy" event and call this function from that, while preventing the default, though I haven't tried that, and you may have to take more care about when to call it.  but that might work.

Hope that gives you what you need.

Davide


--
You received this message because you are subscribed to the Google Groups "MathJax Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mathjax-user...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/mathjax-users/0dbffad2-2603-49df-bd7f-9861d10848aan%40googlegroups.com.
<Screenshot 2024-12-20 020955.png>

Reply all
Reply to author
Forward
0 new messages