Closed saraOrkide closed 4 months ago
Yes, 4.0.0-beta.4 does not get the width of text correct when mtextInheritFont
is true and scale
is not 1. This was fixed several months ago in mathjax/MathJax-src#1014, but there has not been a beta release since then. You can incorporate the following configuration:
MathJax = {
output: {
linebreaks: {inline: false},
mtextInheritFont: true,
scale: 1.2
},
startup: {
ready() {
const {CHTML} = MathJax._.output.chtml_ts;
Object.assign(CHTML.prototype, {
_unknownText: CHTML.prototype.unknownText,
unknownText(text, variant, width = null, rscale = 1) {
const node = this._unknownText(text, variant, width, rscale);
if (width !== null) {
this.adaptor.setStyle(node, 'width', this.fixed(width * this.math.metrics.scale * rscale) + 'em');
}
return node;
},
measureTextNode(textNode) {
const adaptor = this.adaptor;
const text = adaptor.clone(textNode);
adaptor.setStyle(text, 'font-family', adaptor.getStyle(text, 'font-family').replace(/MJXZERO, /g, ''));
const em = this.math.metrics.em;
const style = {
position: 'absolute', top: 0, left: 0,
'white-space': 'nowrap',
'font-size': this.fixed(em, 3) + 'px'
};
const node = this.html('mjx-measure-text', {style}, [text]);
adaptor.append(adaptor.parent(this.math.start.node), this.container);
adaptor.append(this.container, node);
let w = adaptor.nodeSize(text, em)[0];
adaptor.remove(this.container);
adaptor.remove(node);
return {w: w, h: .75, d: .2};
}
});
MathJax.startup.defaultReady();
}
}
}
as a work-around until beta.5 is released.
I should point out that there are a number of issues with your MathJax configuration. You seem to be mixing v2 options with the v3/v4 configuration, and other options are out of place.
For example,
extensions: ["mml2jax.js", "MathMenu.js", "MathZoom.js"],
MathML: {
extensions: ["mml3.js"]
},
are v2 options, and have not effect in v3/v4. It is also a bit odd to set enableMenu
to false, but indicate you want the MathMenu
here.
The options
mtextFont: 'fontRegular',
...
linebreaks: {
inline: !0,
width: "100%",
lineleading: 2,
LinebreakVisitor: null
},
are in the wrong place, as they should be in the chtml
block. I'm not sure what fontRegular
is, but it should be a font name or list of names. The line breaks
values are all the defaults, so you don't need them to be set here.
The option
mtextFontSize: 15,
doesn't exist, so has no effect.
The options
includeHtmlTags: {
br: "\n",
wbr: "",
"#comment": ""
},
ignoreHtmlClass: "tex2jax_ignore",
processHtmlClass: "tex2jax_process",
all belong in the options
block, not in the top-level of the configuration. Since the includeHtmlTags
options are all the defaults, there is no need to include them at all.
Since you are using MathML input, not TeX, the block
tex: {
inlineMath: [["$", "$"]],
processEscapes: !1
},
is superfluous, unless you are using TeX notation elsewhere. And the tex2jax_ignore
and tex2jax_process
values are not used for MathML input, so they don't need to be included here.
As for
load: ["[tex]/tagformat", "output/chtml"],
you are loading the [tex]/tagformat
TeX extension, but are not using TeX, and haven't configured the tag formats, which is the only reason for loading that extension. Plus you haven't added it to the TeX package list, so you are loading code you don't need. Since you aren't loading the MathML input component, I assume you are using one of the combined components, like mml-chtml.js
or perhaps tex-mml-chtml.js
(though that would be more than you need if you aren't actually using TeX input). Those combined components already include the CHTML output component, so there is no need to load it by hand. So your load
array is unnecessary.
Finally, in
chtml: {
displayAlign: 'right',
scale: 1.2,
minScale: .75,
mtextInheritFont: !0,
merrorInheritFont: !0,
skipAttributes: {},
exFactor: 18,
displayAlign: "center",
displayIndent: "0",
matchFontHeight: 0,
adaptiveCSS: !0
},
you have specified displayAlign
twice so the second one ('center'
) will be used. Since you have disabled matchFontHeight
, the minScale
value will not be used, so no need to specify it. The skipAttributes
, second displayAlign
, displayIndent
, and adaptiveCSS
options are all the defaults, so no need to include them here.
The exFactor
is only used when the surrounding font's ex-height can't be computed (as is the case for node applications, but never for in-browser use), so is unneeded in your case. Also, your value of 18 means that the height of an ex
is 18em, or 18 times with width of an M
. If that were true, it would be a very strange font indeed.
So a minimal configuration that is equivalent to the one you have would be:
window.MathJax = {
options: {
enableMenu: !1
},
loader: {
paths: {
"mathjax-modern": "https://cdn.chista.me/chista-mathjax-4.0.0-beta.4/mathjax-modern-font"
}
},
chtml: {
displayAlign: 'right',
scale: 1.2,
mtextInheritFont: !0,
merrorInheritFont: !0,
matchFontHeight: 0
},
startup: {
ready() {
const t = MathJax._.input.tex.ParseMethods.default,
{ RegExpMap: a } = MathJax._.input.tex.TokenMap;
new a("digit", t.digit, /[\d.٫۰-۹]/);
const { ChtmlMn: e } = MathJax._.output.chtml.Wrappers.mn;
e.prototype.remapChars = function (t) {
const a = [];
for (const e of t) {
const t = this.font.getRemappedChar("mn", e);
a.push(...(t ? this.unicodeChars(t, this.variant) : [e]));
}
return a;
};
const { FontData: n } = MathJax._.output.common.FontData,
o = n.defaultMnMap;
for (var s = 0; s < 10; s++) o[48 + s] = String.fromCodePoint(1776 + s);
MathJax.startup.defaultReady();
}
}
});
One of the reasons you have run into this width issue is that your re using <mtext>
elements inappropriately. For example,
<mtext>f(x)</mtext>
should be
<mi>f</mi>
<mrow>
<mo>(<mo>
<mi>x</mi>
<mo>)</mo>
</mrow>
If you put everything into <mtext>
tags, the spacing and italicization will not be correct. It will also produce the wrong results for users with assistive technology like screen readers (but since you have disabled the MathJax menu, they won't be able to turn on the accessibility, so perhaps you don't care about that).
Since the width issue only affect <mtext>
content with scale
not equal to 1, had you used the proper MathML markup, you would have not had the overlap issue, except for when you actually do need <mtext>
, like around Persian words embedded in an expression.
I should point out that there are a number of issues with your MathJax configuration. You seem to be mixing v2 options with the v3/v4 configuration, and other options are out of place. ...
If you don't use load: ["[tex]/tagformat"]
because I use the following code, there is an error:
MathJax(?): Cannot read properties of undefined (reading 'ParseMethods')
I'm using code for persian digit:
const t = MathJax._.input.tex.ParseMethods.default,
{ RegExpMap: a } = MathJax._.input.tex.TokenMap;
new a("digit", t.digit, /[\d.٫۰-۹]/);
const { ChtmlMn: e } = MathJax._.output.chtml.Wrappers.mn;
e.prototype.remapChars = function (t) {
const a = [];
for (const e of t) {
const t = this.font.getRemappedChar("mn", e);
a.push(...(t ? this.unicodeChars(t, this.variant) : [e]));
}
return a;
};
const { FontData: n } = MathJax._.output.common.FontData,
o = n.defaultMnMap;
for (var s = 0; s < 10; s++) o[48 + s] = String.fromCodePoint(1776 + s);
Since you aren't using TeX input (you are using mml-xhtml.js
, so no TeX), you can drop the lines
const t = MathJax._.input.tex.ParseMethods.default,
{ RegExpMap: a } = MathJax._.input.tex.TokenMap;
new a("digit", t.digit, /[\d.٫۰-۹]/);
since they are for TeX, and aren't needed for MathML. That will avoid the error without having to load the tagformat
extension (which will cause all the TeX input code to be loaded unnecessarily).
I fixed the small problem of displaying indices in the formulas according to what you said
But now I have another problem, if the index is written in capital letters, it will be too big
Do you think there is a solution for it?
example: The first part of the formula before equalization, in my opinion, the A index is too big
mml code:
` <div class='chistaItem'
style='text-align:left;justify-content:left;/MARK-BY-CHISTA-PARSER/;direction:ltr;/MARK-BY-CHISTA-PARSER/;'>
<math xmlns='http://www.w3.org/1998/Math/MathML'
display='inline' mathcolor='#050038'>
<mtext>Δ</mtext>
<msub>
<mrow>
<mtext>p</mtext>
</mrow>
<mrow>
<mtext>AB</mtext>
</mrow>
</msub>
<mo>=</mo>
<msub>
<mrow>
<mtext>ρ</mtext>
</mrow>
<mrow>
<mtext>g</mtext>
</mrow>
</msub>
<mfrac>
<mrow>
<mtext>۵</mtext>
</mrow>
<mrow>
<mtext>۱۰۰</mtext>
</mrow>
</mfrac>
<mo>+</mo>
<msub>
<mrow>
<mover accent='true'>
<mrow>
<mtext>ρ</mtext>
</mrow>
<mo>´</mo>
</mover>
</mrow>
<mrow>
<mtext>g</mtext>
</mrow>
</msub>
<mtext>Δ</mtext>
<msub>
<mrow>
<mover accent='true'>
<mrow>
<mtext>P</mtext>
</mrow>
<mo>´</mo>
</mover>
</mrow>
<mrow>
<mtext>AB</mtext>
</mrow>
</msub>
<mfrac>
<mrow>
<mtext>۵</mtext>
</mrow>
<mrow>
<mtext>۱۰۰</mtext>
</mrow>
</mfrac>
</math></span></span></div>`
persian font: Dana-Regular.zip mathjax setting: `(window.MathJax = { options: { enableMenu: !1, }, loader: { paths: { "mathjax-fira": "https://cdn.chista.me/chista-mathjax-4.0.0-beta.4/mathjax-fira-font", } }, chtml: { displayAlign: 'right', scale: 1, merrorInheritFont: !0, matchFontHeight: false, mtextFont: 'fontRegular, Noto Sans, sans-serif', mtextInheritFont: false, unknownFamily: 'fontRegular, Noto Sans, sans-serif', font: 'mathjax-fira', },
startup: {
ready() {
const { ChtmlMn: e } = MathJax._.output.chtml.Wrappers.mn;
e.prototype.remapChars = function (t) {
const a = [];
for (const e of t) {
const t = this.font.getRemappedChar("mn", e);
a.push(...(t ? this.unicodeChars(t, this.variant) : [e]));
}
return a;
};
const { FontData: n } = MathJax._.output.common.FontData,
o = n.defaultMnMap;
for (var s = 0; s < 10; s++) o[48 + s] = String.fromCodePoint(1776 + s);
const { CHTML } = MathJax._.output.chtml_ts;
Object.assign(CHTML.prototype, {
_unknownText: CHTML.prototype.unknownText,
unknownText(text, variant, width = null, rscale = 1) {
const node = this._unknownText(text, variant, width, rscale);
if (width !== null) {
this.adaptor.setStyle(node, 'width', this.fixed(width * this.math.metrics.scale * rscale) + 'em');
}
return node;
},
measureTextNode(textNode) {
const adaptor = this.adaptor;
const text = adaptor.clone(textNode);
adaptor.setStyle(text, 'font-family', adaptor.getStyle(text, 'font-family').replace(/MJXZERO, /g, ''));
const em = this.math.metrics.em;
const style = {
position: 'absolute', top: 0, left: 0,
'white-space': 'nowrap',
'font-size': this.fixed(em, 3) + 'px'
};
const node = this.html('mjx-measure-text', { style }, [text]);
adaptor.append(adaptor.parent(this.math.start.node), this.container);
adaptor.append(this.container, node);
let w = adaptor.nodeSize(text, em)[0];
adaptor.remove(this.container);
adaptor.remove(node);
return { w: w, h: .85, d: .3 };
}
});
const { MmlMath } = MathJax._.core.MmlTree.MmlNodes.math;
const { MmlMstyle } = MathJax._.core.MmlTree.MmlNodes.mstyle;
MmlMath.defaults.scriptsizemultiplier = MmlMstyle.defaults.scriptsizemultiplier = 1;
MathJax.startup.defaultReady();
const params = MathJax.startup.document.outputJax.font.params;
params.rule_thickness = .130;
params.rule_factor = .75;
},
},
});`
using mml-chtml.js version: mathjax-4.0.0-beta.4
Can you provide a screen shot for the following expression:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<msub>
<mtext>A</mtext>
<mtext>A</mtext>
</msub>
<msub>
<mi mathvariant="normal">A</mi>
<mi mathvariant="normal">A</mi>
</msub>
<msub>
<mtext>p</mtext>
<mtext>p</mtext>
</msub>
<msub>
<mi mathvariant="normal">p</mi>
<mi mathvariant="normal">p</mi>
</msub>
</math>
Thanks.
Also, it is best to open a new issue rather than reopen an old one, when you have a new problem to report.
Can you provide a screen shot for the following expression:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> <msub> <mtext>A</mtext> <mtext>A</mtext> </msub> <msub> <mi mathvariant="normal">A</mi> <mi mathvariant="normal">A</mi> </msub> <msub> <mtext>p</mtext> <mtext>p</mtext> </msub> <msub> <mi mathvariant="normal">p</mi> <mi mathvariant="normal">p</mi> </msub> </math>
Thanks.
Also, it is best to open a new issue rather than reopen an old one, when you have a new problem to report.
Yes, sure, I thought it would be better this way, I apologize
Can you provide a screen shot for the following expression:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> <msub> <mtext>A</mtext> <mtext>A</mtext> </msub> <msub> <mi mathvariant="normal">A</mi> <mi mathvariant="normal">A</mi> </msub> <msub> <mtext>p</mtext> <mtext>p</mtext> </msub> <msub> <mi mathvariant="normal">p</mi> <mi mathvariant="normal">p</mi> </msub> </math>
Thanks. Also, it is best to open a new issue rather than reopen an old one, when you have a new problem to report.
Yes, sure, I thought it would be better this way, I apologize
Thanks for the screen shot. It looks like something in your MathJax configuration or CSS is preventing subscripts from being reduced in size.
At one point, I gave you code for changing the scriptsizemultiplier
; what did you set that to?
Do you have any CSS that is intended to affect MathJax output, and if so, what is it?
Does your browser have a minimum font size setting, and if so, what is it?
In the past, the subscripts where properly sized (see your screen shots in #3176, for example), so something you have changed since then is causing this.
I didn't change anything, just what happened
If the index with capital letters is attached to a small letter, it would not be displayed very well in my opinion, like this
I also changed the font size from 13px to 14px
I also set scriptsizemultiplier to 1
Also, I was using Iran Yakan font, I changed it to Dana font
If both numbers are lowercase or both uppercase, there is no problem, everything is correct
I think there is a way to fix it with this dana font
I think it is from this piece of code that you sent me:
measureTextNode(textNode) {
const adaptor = this.adaptor;
const text = adaptor.clone(textNode);
adaptor.setStyle(text, 'font-family', adaptor.getStyle(text, 'font-family').replace(/MJXZERO, /g, ''));
const em = this.math.metrics.em;
const style = {
position: 'absolute', top: 0, left: 0,
'white-space': 'nowrap',
'font-size': this.fixed(em, 3) + 'px'
};
const node = this.html('mjx-measure-text', { style }, [text]);
adaptor.append(adaptor.parent(this.math.start.node), this.container);
adaptor.append(this.container, node);
let w = adaptor.nodeSize(text, em)[0];
adaptor.remove(this.container);
adaptor.remove(node);
return { w: w, h: 1, d: .3 };
}
I had changed the value of h to .85 because signs like radical were displayed too long
If I reduce this value to 1, the situation will be better:
radical Screenshot:
I also set
scriptsizemultiplier
to 1
That is what is causing the problem. The scriptsizemultiplier
is the factor by which the scale of super- and subscripts are determined from the scale of the base. A value of .5 would mean it is half the size of the base. The default is 1/sqrt(2), or about .707. A value of 1 means the subscript is the same size as the base (no reduction in size), which is what you are seeing. So MathJax is doing exactly what you asked it to.
If the index with capital letters is attached to a small letter, it would not be displayed very well in my opinion,
I agree, but that is what you have requested by setting scriptsizemultiplier
to 1.
I had changed the value of
h
to .85 because signs like radical were displayed too long
I don't know if the images you presented are for h = .85
or h = 1
, and whether you are saying these are bad or OK.
Setting h=.85
is probably OK, and setting d = .2
or maybe even .15 would probably also be OK. These are the height and depth of the characters in the font, but setting them too small may mean the line over a radical may hit the top of some characters, or the bottom of some might hit the fraction line if they are in the numerator. You will have to set these based on the font you are using and testing various letters with ascenders and descenders.
Thank you very much for your explanation
Can you explain about the following
const params = MathJax.startup.document.outputJax.font.params; params.rule_thickness = .130; params.rule_factor = .75;
I don't know if the images you presented are for h = .85 or h = 1, and whether you are saying these are bad or OK.
For h = 1 it is not good in my opinion
I set these settings and sent you a screenshot As you can see, for example, the parentheses are attached to the water index And the index that has uppercase letters is not shown very well based on lowercase letters
startup: {
ready() {
const { ChtmlMn: e } = MathJax._.output.chtml.Wrappers.mn;
e.prototype.remapChars = function (t) {
const a = [];
for (const e of t) {
const t = this.font.getRemappedChar("mn", e);
a.push(...(t ? this.unicodeChars(t, this.variant) : [e]));
}
return a;
};
const { FontData: n } = MathJax._.output.common.FontData,
o = n.defaultMnMap;
for (var s = 0; s < 10; s++) o[48 + s] = String.fromCodePoint(1776 + s);
const { CHTML } = MathJax._.output.chtml_ts;
Object.assign(CHTML.prototype, {
_unknownText: CHTML.prototype.unknownText,
unknownText(text, variant, width = null, rscale = 1) {
const node = this._unknownText(text, variant, width, rscale);
if (width !== null) {
this.adaptor.setStyle(node, 'width', this.fixed(width * this.math.metrics.scale * rscale) + 'em');
}
return node;
},
measureTextNode(textNode) {
const adaptor = this.adaptor;
const text = adaptor.clone(textNode);
adaptor.setStyle(text, 'font-family', adaptor.getStyle(text, 'font-family').replace(/MJXZERO, /g, ''));
const em = this.math.metrics.em;
const style = {
position: 'absolute', top: 0, left: 0,
'white-space': 'nowrap',
'font-size': this.fixed(em, 3) + 'px'
};
const node = this.html('mjx-measure-text', { style }, [text]);
adaptor.append(adaptor.parent(this.math.start.node), this.container);
adaptor.append(this.container, node);
let w = adaptor.nodeSize(text, em)[0];
adaptor.remove(this.container);
adaptor.remove(node);
return { w: w, h: .85, d: .15 };
}
});
const { MmlMath } = MathJax._.core.MmlTree.MmlNodes.math;
const { MmlMstyle } = MathJax._.core.MmlTree.MmlNodes.mstyle;
MmlMath.defaults.scriptsizemultiplier = MmlMstyle.defaults.scriptsizemultiplier = .875;
MathJax.startup.defaultReady();
const params = MathJax.startup.document.outputJax.font.params;
params.rule_thickness = .130;
params.rule_factor = .75;
},
},
Can you explain about the following
const params = MathJax.startup.document.outputJax.font.params; params.rule_thickness = .130; params.rule_factor = .75;
Yes, please see the comment where I gave you those changes. This was in response to your asking for more space between fraction lines and the numerator and denominator.
the parentheses are attached to the water index
This is an error in the code I gave you. The * rscale
should be removed from the line
this.adaptor.setStyle(node, 'width', this.fixed(width * this.math.metrics.scale * rscale) + 'em');
making it
this.adaptor.setStyle(node, 'width', this.fixed(width * this.math.metrics.scale) + 'em');
instead.
And the index that has uppercase letters is not shown very well based on lowercase letters
The size of the subscripts are controlled by the scriptsizemultiplier
, which you have set to .875, so there is not much shrinkage, so capital letters will be pretty big (only 12.5% smaller than the base characters).
If you don't want to make the subscripts smaller, there is another parameter that is used in determining how far down to put subscripts. If you set
params.sub1 = .3;
along with the changes to rule_thickness
and rule_factor
, that will push the subscripts down further. The default value is .15; adjust the value to your preferences. Note that this affects both upper- and lower-case letters.
When I set the scale to 1.2 and mtextInheritFont = true, the formulas stick together
![Screenshot from 2024-02-24 16-00-48](https://github.com/mathjax/MathJax/assets/10929451/7ce32c75-4fa6-444c-ad70-eed84c054013)
mathjax version: 4.0.0-beta.4 using mml-chtml.js mathjax config:
using iran-yekan persian font : IRANYekanXFaNum-Regular.zip exmple mml for image number 2: