feat: allow to copy math-jax as tex from github iframe ipynb

This commit is contained in:
Michal Szczepanski 2023-01-30 02:35:00 +01:00
parent 810fc1998b
commit 4decc34c6e
3 changed files with 50 additions and 1 deletions

31
package-lock.json generated

@ -16,6 +16,7 @@
"css": "^3.0.0", "css": "^3.0.0",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"marked": "^4.2.5", "marked": "^4.2.5",
"mathml-to-latex": "^1.2.0",
"nanoid": "^4.0.0", "nanoid": "^4.0.0",
"openpgp": "^5.5.0", "openpgp": "^5.5.0",
"prosemirror-commands": "^1.3.1", "prosemirror-commands": "^1.3.1",
@ -14425,6 +14426,14 @@
"node": ">= 12" "node": ">= 12"
} }
}, },
"node_modules/mathml-to-latex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mathml-to-latex/-/mathml-to-latex-1.2.0.tgz",
"integrity": "sha512-AgwKE5vYJItWsi7qrzzxD8h+YUbv/FH1p1XOs/v/pVFUXHaK+GQZvrU8h7LYmkkfM97zFIPfbWrXJT4Qowykug==",
"dependencies": {
"xmldom": "^0.4.0"
}
},
"node_modules/mdn-data": { "node_modules/mdn-data": {
"version": "2.0.14", "version": "2.0.14",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
@ -16216,6 +16225,15 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true "dev": true
}, },
"node_modules/xmldom": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.4.0.tgz",
"integrity": "sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA==",
"deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/xxhash-wasm": { "node_modules/xxhash-wasm": {
"version": "0.4.2", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz", "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz",
@ -25311,6 +25329,14 @@
"resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz",
"integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==" "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ=="
}, },
"mathml-to-latex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mathml-to-latex/-/mathml-to-latex-1.2.0.tgz",
"integrity": "sha512-AgwKE5vYJItWsi7qrzzxD8h+YUbv/FH1p1XOs/v/pVFUXHaK+GQZvrU8h7LYmkkfM97zFIPfbWrXJT4Qowykug==",
"requires": {
"xmldom": "^0.4.0"
}
},
"mdn-data": { "mdn-data": {
"version": "2.0.14", "version": "2.0.14",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
@ -26640,6 +26666,11 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true "dev": true
}, },
"xmldom": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.4.0.tgz",
"integrity": "sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA=="
},
"xxhash-wasm": { "xxhash-wasm": {
"version": "0.4.2", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz", "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz",

@ -59,6 +59,7 @@
"css": "^3.0.0", "css": "^3.0.0",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"marked": "^4.2.5", "marked": "^4.2.5",
"mathml-to-latex": "^1.2.0",
"nanoid": "^4.0.0", "nanoid": "^4.0.0",
"openpgp": "^5.5.0", "openpgp": "^5.5.0",
"prosemirror-commands": "^1.3.1", "prosemirror-commands": "^1.3.1",

@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { HtmlComponent } from '../../../../common/model/html.model'; import { HtmlComponent } from '../../../../common/model/html.model';
import MathMLToLaTeX from 'mathml-to-latex';
import { PinComponent } from '../../pin.component'; import { PinComponent } from '../../pin.component';
import { applyStylesToElement } from '../../../../common/style.utils'; import { applyStylesToElement } from '../../../../common/style.utils';
import { fnConsoleLog } from '../../../../common/fn/console.fn'; import { fnConsoleLog } from '../../../../common/fn/console.fn';
@ -38,6 +39,13 @@ export class ActionCopyButton implements HtmlComponent<HTMLElement> {
this.el.removeEventListener('click', this.handleClick); this.el.removeEventListener('click', this.handleClick);
} }
private findMathJaxParent = (ref: HTMLElement): HTMLElement => {
if (ref.parentElement && ref.parentElement.tagName.startsWith('MJX-')) {
return this.findMathJaxParent(ref.parentElement);
}
return ref;
};
private handleClick = () => { private handleClick = () => {
let text = ''; let text = '';
const clipboardCopy = this.parent.ref.getElementsByTagName('clipboard-copy'); const clipboardCopy = this.parent.ref.getElementsByTagName('clipboard-copy');
@ -47,11 +55,20 @@ export class ActionCopyButton implements HtmlComponent<HTMLElement> {
if (!text && this.parent.ref.tagName === 'IMG') { if (!text && this.parent.ref.tagName === 'IMG') {
text = this.parent.ref.getAttribute('alt') || ''; text = this.parent.ref.getAttribute('alt') || '';
} }
// Support for math-jax copy as tex inside iframe
// Sample url https://github.com/mholtrop/QMPython/blob/master/Solving_the_Schrodinger_Equation_Numerically.ipynb
if (this.parent.ref.tagName.startsWith('MJX-')) {
// find mathjax and then find math tag inside it
const mathJaxContainer = this.findMathJaxParent(this.parent.ref);
const mathTag = mathJaxContainer.getElementsByTagName('math')[0];
if (mathTag?.parentElement) {
text = MathMLToLaTeX.convert(mathTag.parentElement.innerHTML);
}
}
if (!text) { if (!text) {
text = this.parent.ref.innerText.replaceAll('\u00a0', ' '); text = this.parent.ref.innerText.replaceAll('\u00a0', ' ');
} }
// window.navigator.clipboard not working in iframe :/ // window.navigator.clipboard not working in iframe :/
// TODO
const copyFn = (event: ClipboardEvent) => { const copyFn = (event: ClipboardEvent) => {
fnConsoleLog('COPY FN', event.clipboardData, 'text :', text, 'ref', this.parent.ref); fnConsoleLog('COPY FN', event.clipboardData, 'text :', text, 'ref', this.parent.ref);
event.preventDefault(); event.preventDefault();