diff --git a/src/buildMathML.js b/src/buildMathML.js
index c49aff2d40..376814e89d 100644
--- a/src/buildMathML.js
+++ b/src/buildMathML.js
@@ -128,6 +128,30 @@ export const getVariant = function(
return null;
};
+/**
+ * Check for . which is how a dot renders in MathML,
+ * or ,
+ * which is how a braced comma {,} renders in MathML
+ */
+function isNumberPunctuation(group: ?MathNode): boolean {
+ if (!group) {
+ return false;
+ }
+ if (group.type === 'mi' && group.children.length === 1) {
+ const child = group.children[0];
+ return child instanceof TextNode && child.text === '.';
+ } else if (group.type === 'mo' && group.children.length === 1 &&
+ group.getAttribute('separator') === 'true' &&
+ group.getAttribute('lspace') === '0em' &&
+ group.getAttribute('rspace') === '0em'
+ ) {
+ const child = group.children[0];
+ return child instanceof TextNode && child.text === ',';
+ } else {
+ return false;
+ }
+}
+
/**
* Takes a list of nodes, builds them, and returns a list of the generated
* MathML nodes. Also combine consecutive outputs into a single
@@ -165,13 +189,25 @@ export const buildExpression = function(
lastGroup.children.push(...group.children);
continue;
// Concatenate ... followed by .
- } else if (group.type === 'mi' && group.children.length === 1 &&
- lastGroup.type === 'mn') {
- const child = group.children[0];
- if (child instanceof TextNode && child.text === '.') {
- lastGroup.children.push(...group.children);
- continue;
+ } else if (isNumberPunctuation(group) && lastGroup.type === 'mn') {
+ lastGroup.children.push(...group.children);
+ continue;
+ // Concatenate . followed by ...
+ } else if (group.type === 'mn' && isNumberPunctuation(lastGroup)) {
+ group.children = [...lastGroup.children, ...group.children];
+ groups.pop();
+ // Put preceding ... or . inside base of
+ // ...base......exponent... (or )
+ } else if ((group.type === 'msup' || group.type === 'msub') &&
+ group.children.length >= 1 &&
+ (lastGroup.type === 'mn' || isNumberPunctuation(lastGroup))
+ ) {
+ const base = group.children[0];
+ if (base instanceof MathNode && base.type === 'mn') {
+ base.children = [...lastGroup.children, ...base.children];
+ groups.pop();
}
+ // \not
} else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) {
const lastChild = lastGroup.children[0];
if (lastChild instanceof TextNode && lastChild.text === '\u0338' &&
diff --git a/src/mathMLTree.js b/src/mathMLTree.js
index 9e0cc9f570..3b59183682 100644
--- a/src/mathMLTree.js
+++ b/src/mathMLTree.js
@@ -95,7 +95,18 @@ export class MathNode implements MathDomNode {
}
for (let i = 0; i < this.children.length; i++) {
- node.appendChild(this.children[i].toNode());
+ // Combine multiple TextNodes into one TextNode, to prevent
+ // screen readers from reading each as a separate word [#3995]
+ if (this.children[i] instanceof TextNode &&
+ this.children[i + 1] instanceof TextNode) {
+ let text = this.children[i].toText() + this.children[++i].toText();
+ while (this.children[i + 1] instanceof TextNode) {
+ text += this.children[++i].toText();
+ }
+ node.appendChild(new TextNode(text).toNode());
+ } else {
+ node.appendChild(this.children[i].toNode());
+ }
}
return node;
diff --git a/test/__snapshots__/mathml-spec.js.snap b/test/__snapshots__/mathml-spec.js.snap
index 8505c2718c..2a784ff1a2 100644
--- a/test/__snapshots__/mathml-spec.js.snap
+++ b/test/__snapshots__/mathml-spec.js.snap
@@ -428,9 +428,35 @@ exports[`A MathML builder should concatenate digits into single 1`] = `
0.34
+
+ =
+
+
+
+ .34
+
+
+ 1
+
+
+
+
+ \\sin{\\alpha}=0.34=.34^1
+
+
+
+`;
+
+exports[`A MathML builder should concatenate digits into single 2`] = `
+
diff --git a/test/mathml-spec.js b/test/mathml-spec.js
index 8965c597da..94a4b42468 100644
--- a/test/mathml-spec.js
+++ b/test/mathml-spec.js
@@ -29,7 +29,8 @@ describe("A MathML builder", function() {
});
it('should concatenate digits into single ', () => {
- expect(getMathML("\\sin{\\alpha}=0.34")).toMatchSnapshot();
+ expect(getMathML("\\sin{\\alpha}=0.34=.34^1")).toMatchSnapshot();
+ expect(getMathML("1{,}000{,}000")).toMatchSnapshot();
});
it('should make prime operators into nodes', () => {