diff --git a/src/buildHTML.js b/src/buildHTML.js index 5deb4fa5..4180b1bf 100644 --- a/src/buildHTML.js +++ b/src/buildHTML.js @@ -49,6 +49,23 @@ const isBinRightCanceller = function(node, isRealGroup) { } }; +/** + * Splice out any spaces from `children` starting at position `i`, and return + * the spliced-out array. Returns null if `children[i]` does not exist or is not + * a space. + */ +const spliceSpaces = function(children, i) { + let j = i; + while (j < children.length && isSpace(children[j])) { + j++; + } + if (j === i) { + return null; + } else { + return children.splice(i, j - i); + } +}; + /** * Take a list of nodes, build them in order, and return a list of the built * nodes. documentFragments are flattened into their contents, so the @@ -74,24 +91,18 @@ const buildExpression = function(expression, options, isRealGroup) { // spacing (e.g., "add thick space between mord and mrel"). Since CSS // adjacency rules implement atom spacing, spaces should be invisible to // CSS. So we splice them out of `groups` and into the atoms themselves. - let spaces = null; for (let i = 0; i < groups.length; i++) { - if (isSpace(groups[i])) { - spaces = spaces || []; - spaces.push(groups[i]); - groups.splice(i, 1); - i--; - } else if (spaces) { + const spaces = spliceSpaces(groups, i); + if (spaces && i < groups.length) { if (groups[i] instanceof domTree.symbolNode) { groups[i] = makeSpan([].concat(groups[i].classes), [groups[i]]); } buildCommon.prependChildren(groups[i], spaces); - spaces = null; + } else if (spaces) { + Array.prototype.push.apply(groups, spaces); + break; } } - if (spaces) { - Array.prototype.push.apply(groups, spaces); - } // Binary operators change to ordinary symbols in some contexts. for (let i = 0; i < groups.length; i++) { @@ -1278,11 +1289,17 @@ groupTypes.leftright = function(group, options) { // Handle middle delimiters if (hadMiddle) { for (let i = 1; i < inner.length; i++) { - if (inner[i].isMiddle) { + const middleDelim = inner[i]; + if (middleDelim.isMiddle) { // Apply the options that were active when \middle was called inner[i] = delimiter.leftRightDelim( - inner[i].isMiddle.value, innerHeight, innerDepth, - inner[i].isMiddle.options, group.mode, []); + middleDelim.isMiddle.value, innerHeight, innerDepth, + middleDelim.isMiddle.options, group.mode, []); + // Add back spaces shifted into the delimiter + const spaces = spliceSpaces(middleDelim.children, 0); + if (spaces) { + buildCommon.prependChildren(inner[i], spaces); + } } } } diff --git a/test/screenshotter/images/LeftRightMiddle-chrome.png b/test/screenshotter/images/LeftRightMiddle-chrome.png index f731f146..34ed45ed 100644 Binary files a/test/screenshotter/images/LeftRightMiddle-chrome.png and b/test/screenshotter/images/LeftRightMiddle-chrome.png differ diff --git a/test/screenshotter/images/LeftRightMiddle-firefox.png b/test/screenshotter/images/LeftRightMiddle-firefox.png index 4fe9d8c6..64a49f19 100644 Binary files a/test/screenshotter/images/LeftRightMiddle-firefox.png and b/test/screenshotter/images/LeftRightMiddle-firefox.png differ diff --git a/test/screenshotter/ss_data.yaml b/test/screenshotter/ss_data.yaml index 51e6373d..fc1e86cd 100644 --- a/test/screenshotter/ss_data.yaml +++ b/test/screenshotter/ss_data.yaml @@ -86,7 +86,7 @@ Kern: Lap: ab\llap{f}cd\rlap{g}h LeftRight: \left( x^2 \right) \left\{ x^{x^{x^{x^x}}} \right. LeftRightListStyling: a+\left(x+y\right)-x -LeftRightMiddle: \left( x^2 \middle/ \right) \left\{ x^{x^{x^{x^x}}} \middle/ y \right. +LeftRightMiddle: \left( x^2 \middle/ \right) \left\{ x^{x^{x^{x^x}}} \middle/ y \right.\left(x\middle|y\,\middle|\,z\right) LeftRightStyleSizing: | +\left\{\rule{0.1em}{1em}\right. x^{+\left\{\rule{0.1em}{1em}\right.