MathJax's output is not intended for direct copying via selection, and it would make sense to do so only for the simplest of expressions (e.g., no fractions, square roots, exponents, and so on).
It is possible to provide the ability to copy the original TeX source when the expression is selected, however. You could use the following configuration to do so:
<script>
MathJax = {
options: {
renderActions: {
addCopyText: [155,
(doc) => {for (const math of doc.math) MathJax.config.addCopyText(math, doc)},
(math, doc) => MathJax.config.addCopyText(math, doc)
]
}
},
addCopyText(math, doc) {
const adaptor = doc.adaptor;
const text = adaptor.node('mjx-copytext', {'aria-hidden': true}, [
adaptor.text(math.start.delim + math.math + math.end.delim)
]);
adaptor.append(math.typesetRoot, text);
},
startup: {
ready() {
MathJax._.output.chtml_ts.CHTML.commonStyles['mjx-copytext'] = {
display: 'inline-block',
position: 'absolute',
top: 0, left: 0, width: 0, height: 0,
opacity: 0,
overflow: 'hidden'
};
MathJax.startup.defaultReady();
}
}
}
</script>
This attaches a visually hidden element to the MathJax output that contains the original TeX code as text that will be selected when the typeset math is part of a selection. That means it will be copied to the clipboard in place of the MathJax output (which can't be selected, as you point out). This should allow you to select a paragraph with typeset math and be able to copy it so that it includes the TeX markup as though it were not typeset.
This only allows selection of the entire expression (not sub-expressions). Also, there is no visual indication that the expression is selected (I could not find a way to include highlighting of the expression when selected). So this is useful but perhaps not optimal.
The reason you can't select the typeset characters themselves is that the CommonHTML output uses CSS content style rules to insert he needed characters into the pag, and CSS content is not selectable. (This was not the case in CommonHTML output in v2, so you could select pieces of if there, but you could not select SVG output, so even in v2, this was not always possible.)
In order to make the text selectable, you would need to override the portions of MathJax that handle the CSS and the character output. That can be done with the following configuration:
<script>
MathJax = {
startup: {
ready() {
const {TeXFont} = MathJax._.output.chtml.fonts.tex_ts;
const {CHTMLFontData} = MathJax._.output.chtml.FontData;
const {CHTMLTextNode} = MathJax._.output.chtml.Wrappers.TextNode;
for (const name of Object.keys(TeXFont.defaultChars)) {
var chars = TeXFont.defaultChars[name];
for (const n of Object.keys(chars)) {
const options = chars[n][3];
if (options && options.c) {
options.c = options.c.replace(/\\[0-9A-F]+/ig, (x) => String.fromCodePoint(parseInt(x.substr(1), 16)));
} else if (options) {
options.c = String.fromCodePoint(parseInt(n));
} else {
chars[n][3] = {c: String.fromCodePoint(parseInt(n))};
}
}
};
delete TeXFont.defaultStyles['mjx-c::before'];
CHTMLFontData.prototype.addCharStyles = function (styles, vclass, n, data, charUsed) {
const [h, d, w, options] = data;
if (this.options.adaptiveCSS && !options.used) return;
const css = {};
const selector = 'mjx-c' + this.charSelector(n);
const root = this.cssRoot;
css.padding = this.padding(data, 0, options.ic || 0);
if (options.f !== undefined) {
css['font-family'] = 'MJXZERO, MJXTEX' + (options.f ? '-' + options.f : '') + '!important';
}
const char = (vclass ? vclass + ' ': '') + selector;
styles[root + char] = css;
if (options.ic) {
const [MJX, noIC] = [root + 'mjx-', '[noIC]' + char + ':last-child'];
styles[MJX + 'mi' + noIC] =
styles[MJX + 'mo' + noIC] = {
'padding-right': this.em(w)
};
}
};
CHTMLTextNode.prototype.toCHTML = function (parent) {
this.markUsed();
const adaptor = this.adaptor;
const variant = this.parent.variant;
const text = this.node.getText();
if (variant === '-explicitFont') {
const font = this.jax.getFontData(this.parent.styles);
adaptor.append(parent, this.jax.unknownText(text, variant, font));
} else {
const c = this.parent.stretch.c;
const chars = this.parent.remapChars(c ? [c] : this.unicodeChars(text));
for (const n of chars) {
const data = this.getVariantChar(variant, n)[3];
const node = (data.unknown ?
this.jax.unknownText(String.fromCodePoint(n), variant) :
this.html('mjx-c', {class: this.char(n)}, [this.text(data.c)]));
adaptor.append(parent, node);
data.used = true;
}
}
};
CHTMLTextNode.styles['mjx-c'].width = 0;
MathJax.startup.defaultReady();
}
}
}
</script>
This should be made into an extension (and would be a nice project for a first-tie contributor). For now, you could put it into a separate script file that you load before loading MathJax's tex-html.js file.
Note, however, that although the characters are now selectable, the selection background does not cover the complete glyph. This is due to the way that CommonHTML handles the fonts, and would be difficult to patch by hand like this. We are planning a font update for this summer, an that may change during the font redesign.
I hope one of these does what you need. Of course, you will need to merge these into your existing configuration object.
Davide
Here is my config:
<script>
window.MathJax = {
options: {
renderActions: {
addMenu: [],
checkLoading: []
},
ignoreHtmlClass: 'tex2jax_ignore',
processHtmlClass: 'tex2jax_process'
},
tex: {
inlineMath: [['$','$'], ['\\(','\\)']]
}
};
</script>
The script converts text between $$ into mjx-container tags that can't be copied to clipboard.
How can I change the config so that either the tags have some fallback or they themselves can be copied to plaintext?
--
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 on the web visit
https://groups.google.com/d/msgid/mathjax-users/128a0cf2-2167-40cc-8e98-d67475bc27cf%40googlegroups.com.