Merge "Fix responsive mode not being respected in lit diff line wrapping"
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
index c8663e6..627ea27 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
@@ -198,7 +198,16 @@
     text = htmlEscape(text).toString();
     // Unescape block quotes '>'. This is slightly dangerous as '>' can be used
     // in HTML fragments, but it is insufficient on it's own.
-    text = text.replace(/(^|\n)>/g, '$1>');
+    for (;;) {
+      const newText = text.replace(
+        /(^|\n)((?:\s{0,3}>)*\s{0,3})>/g,
+        '$1$2>'
+      );
+      if (newText === text) {
+        break;
+      }
+      text = newText;
+    }
 
     return text;
   }
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts
index 9acca0f..3881c62 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts
@@ -593,5 +593,27 @@
         `
       );
     });
+
+    test('renders nested block quotes', async () => {
+      element.content = '> > > block quote';
+      await element.updateComplete;
+
+      assert.shadowDom.equal(
+        element,
+        /* HTML */ `
+          <marked-element>
+            <div slot="markdown-html" class="markdown-html">
+              <blockquote>
+                <blockquote>
+                  <blockquote>
+                    <p>block quote</p>
+                  </blockquote>
+                </blockquote>
+              </blockquote>
+            </div>
+          </marked-element>
+        `
+      );
+    });
   });
 });