Repository: jdrouet/mrml (language: python)

Issue:
Preserve whitespace between inline Elements
MRML removes all whitespace between consecutive inline elements inside `mj-text`. This breaks text with simple formatting elements like `em` or `strong`.

With the following input:

```mjml
<mjml>
  <mj-body>
    <mj-text>
      <p>
        <em>foo</em> <strong>bar</strong>
      </p>
    </mj-text>
  </mj-body>
</mjml>
```

MRML generates:

```html
<!doctype html>
<html>
  <!-- ... -->
  <p><em>foo</em><strong>bar</strong></p>
  <!-- ... -->
</html>
```

Whereas MJML generates:

```html
<!doctype html>
<html>
  <!-- ... -->
  <p><em>foo</em> <strong>bar</strong></p>
  <!-- ... -->
</html>
```

Which is expected. 

Tell me if you need more information.


Discussion / hints:

Fix patch:
diff --git a/packages/mrml-core/src/prelude/parser/mod.rs b/packages/mrml-core/src/prelude/parser/mod.rs
index 00f55008..ed71a424 100644
--- a/packages/mrml-core/src/prelude/parser/mod.rs
+++ b/packages/mrml-core/src/prelude/parser/mod.rs
@@ -287,7 +287,9 @@ impl<'a> MrmlCursor<'a> {
             .next()
             .map(|res| res.map_err(Error::from).and_then(MrmlToken::try_from))
             .and_then(|token| match token {
-                Ok(MrmlToken::Text(inner)) if inner.text.trim().is_empty() => {
+                Ok(MrmlToken::Text(inner))
+                    if inner.text.starts_with('\n') && inner.text.trim().is_empty() =>
+                {
                     self.read_next_token()
                 }
                 other => Some(other),
@@ -343,6 +345,9 @@ impl<'a> MrmlCursor<'a> {
     pub(crate) fn assert_element_close(&mut self) -> Result<ElementClose<'a>, Error> {
         match self.next_token() {
             Some(Ok(MrmlToken::ElementClose(inner))) => Ok(inner),
+            Some(Ok(MrmlToken::Text(inner))) if inner.text.trim().is_empty() => {
+                self.assert_element_close()
+            }
             Some(Ok(other)) => Err(Error::UnexpectedToken(other.span())),
             Some(Err(inner)) => Err(inner),
             None => Err(Error::EndOfStream),


Test patch:
diff --git a/packages/mrml-core/tests/issue-439.rs b/packages/mrml-core/tests/issue-439.rs
new file mode 100644
index 00000000..7465597e
--- /dev/null
+++ b/packages/mrml-core/tests/issue-439.rs
@@ -0,0 +1,24 @@
+#![cfg(all(feature = "parse", feature = "render"))]
+
+#[test]
+fn should_preserve_whitespaces() {
+    let template = r#"<mjml>
+  <mj-body>
+    <mj-text>
+      <p>
+        <em>foo</em> <strong>bar</strong>
+      </p>
+    </mj-text>
+  </mj-body>
+</mjml>"#;
+
+    let root = mrml::parse(template).unwrap();
+    let html = root
+        .render(&mrml::prelude::render::RenderOptions::default())
+        .unwrap();
+    assert!(
+        html.contains("<p><em>foo</em> <strong>bar</strong></p>"),
+        "{}",
+        html
+    );
+}