copy-tex.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. (function webpackUniversalModuleDefinition(root, factory) {
  2. if(typeof exports === 'object' && typeof module === 'object')
  3. module.exports = factory();
  4. else if(typeof define === 'function' && define.amd)
  5. define([], factory);
  6. else {
  7. var a = factory();
  8. for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
  9. }
  10. })((typeof self !== 'undefined' ? self : this), function() {
  11. return /******/ (function() { // webpackBootstrap
  12. /******/ "use strict";
  13. var __webpack_exports__ = {};
  14. ;// ./contrib/copy-tex/katex2tex.ts
  15. // Set these to how you want inline and display math to be delimited.
  16. const defaultCopyDelimiters = {
  17. inline: ['$', '$'],
  18. // alternative: ['\(', '\)']
  19. display: ['$$', '$$'] // alternative: ['\[', '\]']
  20. };
  21. // Replace .katex elements with their TeX source (<annotation> element).
  22. // Modifies fragment in-place. Useful for writing your own 'copy' handler,
  23. // as in copy-tex.js.
  24. function katexReplaceWithTex(fragment, copyDelimiters) {
  25. if (copyDelimiters === void 0) {
  26. copyDelimiters = defaultCopyDelimiters;
  27. }
  28. // Remove .katex-html blocks that are preceded by .katex-mathml blocks
  29. // (which will get replaced below).
  30. const katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
  31. for (let i = 0; i < katexHtml.length; i++) {
  32. const element = katexHtml[i];
  33. if (element.remove) {
  34. element.remove();
  35. } else if (element.parentNode) {
  36. element.parentNode.removeChild(element);
  37. }
  38. }
  39. // Replace .katex-mathml elements with their annotation (TeX source)
  40. // descendant, with inline delimiters.
  41. const katexMathml = fragment.querySelectorAll('.katex-mathml');
  42. for (let i = 0; i < katexMathml.length; i++) {
  43. const element = katexMathml[i];
  44. const texSource = element.querySelector('annotation');
  45. if (texSource) {
  46. if (element.replaceWith) {
  47. element.replaceWith(texSource);
  48. } else if (element.parentNode) {
  49. element.parentNode.replaceChild(texSource, element);
  50. }
  51. texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
  52. }
  53. }
  54. // Switch display math to display delimiters.
  55. const displays = fragment.querySelectorAll('.katex-display annotation');
  56. for (let i = 0; i < displays.length; i++) {
  57. const element = displays[i];
  58. element.innerHTML = copyDelimiters.display[0] + element.innerHTML.substr(copyDelimiters.inline[0].length, element.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
  59. }
  60. return fragment;
  61. }
  62. /* harmony default export */ var katex2tex = (katexReplaceWithTex);
  63. ;// ./contrib/copy-tex/copy-tex.ts
  64. // Return <div class="katex"> element containing node, or null if not found.
  65. function closestKatex(node) {
  66. // If node is a Text Node, for example, go up to containing Element,
  67. // where we can apply the `closest` method.
  68. const element = node instanceof Element ? node : node.parentElement;
  69. return element && element.closest('.katex');
  70. }
  71. // Global copy handler to modify behavior on/within .katex elements.
  72. document.addEventListener('copy', function (event) {
  73. const selection = window.getSelection();
  74. if (!selection || selection.isCollapsed || !event.clipboardData) {
  75. return; // default action OK if selection is empty or unchangeable
  76. }
  77. const clipboardData = event.clipboardData;
  78. const range = selection.getRangeAt(0);
  79. // When start point is within a formula, expand to entire formula.
  80. const startKatex = closestKatex(range.startContainer);
  81. if (startKatex) {
  82. range.setStartBefore(startKatex);
  83. }
  84. // Similarly, when end point is within a formula, expand to entire formula.
  85. const endKatex = closestKatex(range.endContainer);
  86. if (endKatex) {
  87. range.setEndAfter(endKatex);
  88. }
  89. const fragment = range.cloneContents();
  90. if (!fragment.querySelector('.katex-mathml')) {
  91. return; // default action OK if no .katex-mathml elements
  92. }
  93. const htmlContents = Array.prototype.map.call(fragment.childNodes, el => el instanceof Text ? el.textContent : el.outerHTML).join('');
  94. // Preserve usual HTML copy/paste behavior.
  95. clipboardData.setData('text/html', htmlContents);
  96. // Rewrite plain-text version.
  97. clipboardData.setData('text/plain', katex2tex(fragment).textContent);
  98. // Prevent normal copy handling.
  99. event.preventDefault();
  100. });
  101. __webpack_exports__ = __webpack_exports__["default"];
  102. /******/ return __webpack_exports__;
  103. /******/ })()
  104. ;
  105. });