Repository: KaTeX/KaTeX (js)
Issue: Hard newline, \\,  fails after relation
A hard newline, `\\,` will properly insert a newline after an ORD atom, as in `M = a \\ b`. But the hard newline is ignored if it follows a relation, as in `M = \\ a`.

LaTeX will insert the newline in either case.
Pull request description: Fix \\ and \newline after operator
Fix #1790.  `\\` and `\newline` render as a span with classes `mspace` and `newline`.  We need to check for `newline` when bringing spaces into the same `base` group.

Patch:
diff --git a/src/buildHTML.js b/src/buildHTML.js
index 88466de3..2822eec8 100644
--- a/src/buildHTML.js
+++ b/src/buildHTML.js
@@ -334,10 +334,11 @@ export default function buildHTML(tree: AnyParseNode[], options: Options): DomSp
             expression[i].hasClass("mrel") ||
             expression[i].hasClass("allowbreak")) {
             // Put any post-operator glue on same line as operator.
-            // Watch for \nobreak along the way.
+            // Watch for \nobreak along the way, and stop at \newline.
             let nobreak = false;
             while (i < expression.length - 1 &&
-                   expression[i + 1].hasClass("mspace")) {
+                   expression[i + 1].hasClass("mspace") &&
+                   !expression[i + 1].hasClass("newline")) {
                 i++;
                 parts.push(expression[i]);
                 if (expression[i].hasClass("nobreak")) {


Test patch:
diff --git a/test/__snapshots__/katex-spec.js.snap b/test/__snapshots__/katex-spec.js.snap
index dd7c81f5..7c224f25 100755
--- a/test/__snapshots__/katex-spec.js.snap
+++ b/test/__snapshots__/katex-spec.js.snap
@@ -858,6 +858,118 @@ exports[`Extending katex by new fonts and symbols Add new font class to new exte
 
 `;
 
+exports[`Newlines via \\\\ and \\newline \\\\ causes newline, even after mrel and mop 1`] = `
+
+<span class="katex">
+  <span class="katex-mathml">
+    <math>
+      <semantics>
+        <mrow>
+          <mi>
+            M
+          </mi>
+          <mo>
+            =
+          </mo>
+          <mspace linebreak="newline">
+          </mspace>
+          <mi>
+            a
+          </mi>
+          <mo>
+            +
+          </mo>
+          <mspace linebreak="newline">
+          </mspace>
+          <mi>
+            b
+          </mi>
+          <mspace linebreak="newline">
+          </mspace>
+          <mi>
+            c
+          </mi>
+        </mrow>
+        <annotation encoding="application/x-tex">
+          M = \\\\ a + \\\\ b \\\\ c
+        </annotation>
+      </semantics>
+    </math>
+  </span>
+  <span class="katex-html"
+        aria-hidden="true"
+  >
+    <span class="base">
+      <span class="strut"
+            style="height:0.68333em;vertical-align:0em;"
+      >
+      </span>
+      <span class="mord mathdefault"
+            style="margin-right:0.10903em;"
+      >
+        M
+      </span>
+      <span class="mspace"
+            style="margin-right:0.2777777777777778em;"
+      >
+      </span>
+      <span class="mrel">
+        =
+      </span>
+      <span class="mspace"
+            style="margin-right:0.2777777777777778em;"
+      >
+      </span>
+    </span>
+    <span class="mspace newline">
+    </span>
+    <span class="base">
+      <span class="strut"
+            style="height:0.66666em;vertical-align:-0.08333em;"
+      >
+      </span>
+      <span class="mord mathdefault">
+        a
+      </span>
+      <span class="mspace"
+            style="margin-right:0.2222222222222222em;"
+      >
+      </span>
+      <span class="mbin">
+        +
+      </span>
+      <span class="mspace"
+            style="margin-right:0.2222222222222222em;"
+      >
+      </span>
+    </span>
+    <span class="mspace newline">
+    </span>
+    <span class="base">
+      <span class="strut"
+            style="height:0.69444em;vertical-align:0em;"
+      >
+      </span>
+      <span class="mord mathdefault">
+        b
+      </span>
+    </span>
+    <span class="mspace newline">
+    </span>
+    <span class="base">
+      <span class="strut"
+            style="height:0.43056em;vertical-align:0em;"
+      >
+      </span>
+      <span class="mord mathdefault">
+        c
+      </span>
+    </span>
+  </span>
+</span>
+
+`;
+
 exports[`href and url commands should not affect spacing around 1`] = `
 [
   {
diff --git a/test/katex-spec.js b/test/katex-spec.js
index 4718e657..fee9de9a 100644
--- a/test/katex-spec.js
+++ b/test/katex-spec.js
@@ -3405,6 +3405,15 @@ describe("Newlines via \\\\ and \\newline", function() {
         expect`a\\b\begin{matrix}x&y\\z&w\end{matrix}\\c`
             .toParseLike`a\newline b\begin{matrix}x&y\cr z&w\end{matrix}\newline c`;
     });
+
+    it("\\\\ causes newline, even after mrel and mop", () => {
+        const markup = katex.renderToString(r`M = \\ a + \\ b \\ c`);
+        // Ensure newlines appear outside base spans (because, in this regexp,
+        // base span occurs immediately after each newline span).
+        expect(markup).toMatch(
+            /(<span class="base">.*?<\/span><span class="mspace newline"><\/span>){3}<span class="base">/);
+        expect(markup).toMatchSnapshot();
+    });
 });
 
 describe("Symbols", function() {