You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
51 lines
1.8 KiB
51 lines
1.8 KiB
// @flow |
|
|
|
import katexReplaceWithTex from './katex2tex'; |
|
|
|
// Return <div class="katex"> element containing node, or null if not found. |
|
function closestKatex(node: Node): ?Element { |
|
// If node is a Text Node, for example, go up to containing Element, |
|
// where we can apply the `closest` method. |
|
const element: ?Element = |
|
(node instanceof Element ? node : node.parentElement); |
|
return element && element.closest('.katex'); |
|
} |
|
|
|
// Global copy handler to modify behavior on/within .katex elements. |
|
document.addEventListener('copy', function(event: ClipboardEvent) { |
|
const selection = window.getSelection(); |
|
if (selection.isCollapsed || !event.clipboardData) { |
|
return; // default action OK if selection is empty or unchangeable |
|
} |
|
const clipboardData = event.clipboardData; |
|
const range = selection.getRangeAt(0); |
|
|
|
// When start point is within a formula, expand to entire formula. |
|
const startKatex = closestKatex(range.startContainer); |
|
if (startKatex) { |
|
range.setStartBefore(startKatex); |
|
} |
|
|
|
// Similarly, when end point is within a formula, expand to entire formula. |
|
const endKatex = closestKatex(range.endContainer); |
|
if (endKatex) { |
|
range.setEndAfter(endKatex); |
|
} |
|
|
|
const fragment = range.cloneContents(); |
|
if (!fragment.querySelector('.katex-mathml')) { |
|
return; // default action OK if no .katex-mathml elements |
|
} |
|
|
|
const htmlContents = Array.prototype.map.call(fragment.childNodes, |
|
(el) => (el instanceof Text ? el.textContent : el.outerHTML) |
|
).join(''); |
|
|
|
// Preserve usual HTML copy/paste behavior. |
|
clipboardData.setData('text/html', htmlContents); |
|
// Rewrite plain-text version. |
|
clipboardData.setData('text/plain', |
|
katexReplaceWithTex(fragment).textContent); |
|
// Prevent normal copy handling. |
|
event.preventDefault(); |
|
});
|
|
|