File size: 1,882 Bytes
bc20498 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
// @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();
});
|