Repository: jugglerchris/rust-html2text (rust)

Issue:
Unexpected newlines between nested lists
Nested lists have newlines and spaces between them when I would expect them not to:

```rust
let input = indoc! {b"
<ul>
    <li>
        Bullet point 1<ul>
            <li>2nd level nested bullet point 1</li>
            <li>2nd level nested bullet point 2
                <ul>
                    <li>3rd level nested bullet point 1</li>
                    <li>
                        3rd level nested bullet point 2
                        <ul>
                            <li>4th level nested bullet point 1</li>
                            <li>4th level nested bullet point 2</li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
    <li>Bullet point 2</li>
</ul>
"};
let expected = indoc! {"
* Bullet point 1
   * 2nd level nested bullet point 1
   * 2nd level nested bullet point 2
      * 3rd level nested bullet point 1
      * 3rd level nested bullet point 2
         * 4th level nested bullet point 1
         * 4th level nested bullet point 2
* Bullet point 2
"};
let actual = html2text::from_read(&input[..], usize::MAX).unwrap();
assert_eq!(actual, expected)
```

Assertion failure:
```
assertion `left == right` failed
  left: "* Bullet point 1\n  \n  * 2nd level nested bullet point 1\n  * 2nd level nested bullet point 2\n    \n    * 3rd level nested bullet point 1\n    * 3rd level nested bullet point 2\n      \n      * 4th level nested bullet point 1\n      * 4th level nested bullet point 2\n* Bullet point 2\n"
 right: "* Bullet point 1\n   * 2nd level nested bullet point 1\n   * 2nd level nested bullet point 2\n      * 3rd level nested bullet point 1\n      * 3rd level nested bullet point 2\n         * 4th level nested bullet point 1\n         * 4th level nested bullet point 2\n* Bullet point 2\n"
```

Actual:
```
* Bullet point 1
  
  * 2nd level nested bullet point 1
  * 2nd level nested bullet point 2
    
    * 3rd level nested bullet point 1
    * 3rd level nested bullet point 2
      
      * 4th level nested bullet point 1
      * 4th level nested bullet point 2
* Bullet point 2
```



Pull request:
Remove redundant extra line before lists.
Fixes #196 

Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 737475f..016f960 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,13 +21,13 @@ unicode-width = "0.2"
 backtrace = { version = "0.3", optional=true }
 thiserror = "2.0.0"
 log = { version = "0.4.20", optional = true }
-nom = "7.1.3"
+nom = { version = "7.1.3", optional = true }
 
 [features]
 html_trace = ["dep:log"]
 html_trace_bt = ["html_trace", "dep:backtrace"]
 default = []
-css = []
+css = [ "dep:nom" ]
 css_ext = ["css"]
 
 [[example]]
diff --git a/src/lib.rs b/src/lib.rs
index c44f276..b0248c6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1981,8 +1981,6 @@ fn do_render_node<T: Write, D: TextDecorator>(
             })
         }
         Ul(items) => {
-            renderer.start_block()?;
-
             let prefix = renderer.unordered_item_prefix();
             let prefix_len = prefix.len();
 
@@ -2013,8 +2011,6 @@ fn do_render_node<T: Write, D: TextDecorator>(
             }
         }
         Ol(start, items) => {
-            renderer.start_block()?;
-
             let num_items = items.len();
 
             // The prefix width could be at either end if the start is negative.
diff --git a/src/render/text_renderer.rs b/src/render/text_renderer.rs
index 1261731..145669d 100644
--- a/src/render/text_renderer.rs
+++ b/src/render/text_renderer.rs
@@ -975,6 +975,33 @@ impl<D: TextDecorator> std::fmt::Debug for SubRenderer<D> {
     }
 }
 
+impl<D: TextDecorator> std::fmt::Display for SubRenderer<D> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        writeln!(f, "SubRenderer(width={})", self.width)?;
+        writeln!(f, " Lines: {}", self.lines.len())?;
+        for line in &self.lines {
+            match line {
+                RenderLine::Text(tagged_line) => {
+                    writeln!(f, "  {}", tagged_line.to_string())?;
+                }
+                RenderLine::Line(_) => {
+                    writeln!(f, "  <<<border>>>")?;
+                }
+            }
+        }
+        if let Some(wrapping) = &self.wrapping {
+            writeln!(f, " WrappedBlock text:")?;
+            for line in &wrapping.text {
+                writeln!(f, "  {}", line.to_string())?;
+            }
+            writeln!(f, " WrappedBlock cur line:")?;
+            writeln!(f, "  {}", wrapping.line.to_string())?;
+            writeln!(f, " WrappedBlock Word: [[{}]]", wrapping.word.to_string())?;
+        }
+        writeln!(f)
+    }
+}
+
 /// Rendering options.
 #[derive(Clone)]
 #[non_exhaustive]


Test patch:
diff --git a/src/tests.rs b/src/tests.rs
index cf19aee..07828e0 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -778,7 +778,6 @@ bit of
 text to
 wrap
 
-
 * This is a
   bit of
   text to
@@ -803,16 +802,13 @@ fn test_wrap_max2() {
         </li></ul>"#,
         r#"plain para at the
 full screen width
-
 * bullet point uses
   same width so its
   margin is 2 chars
   further right
-  
   * nested bullets in
     turn move 2 chars
     right each time
-    
     * result: you never
       get text squashed
       too narrow
@@ -822,6 +818,58 @@ full screen width
     );
 }
 
+#[test]
+fn test_nested_ul() {
+    test_html(
+        br"
+    <ul>
+      <li>Item 1</li>
+      <li>Item 2
+      <ul>
+        <li>SubItem 2.1</li>
+        <li>SubItem 2.2
+          <ul>
+            <li>Sub Item 2.2.1</li>
+          </ul>
+        </li>
+      </ul>
+    </ul>",
+        r#"* Item 1
+* Item 2
+  * SubItem 2.1
+  * SubItem 2.2
+    * Sub Item 2.2.1
+"#,
+        80,
+    );
+}
+
+#[test]
+fn test_nested_ol() {
+    test_html(
+        br"
+    <ol>
+      <li>Item 1</li>
+      <li>Item 2
+      <ol>
+        <li>SubItem 2.1</li>
+        <li>SubItem 2.2
+          <ol>
+            <li>Sub Item 2.2.1</li>
+          </ol>
+        </li>
+      </ol>
+    </ol>",
+        r#"1. Item 1
+2. Item 2
+   1. SubItem 2.1
+   2. SubItem 2.2
+      1. Sub Item 2.2.1
+"#,
+        80,
+    );
+}
+
 #[test]
 fn test_wrap_word_boundaries() {
     test_html(br#"Hello there boo"#, "Hello there boo\n", 20);
@@ -917,7 +965,6 @@ fn test_subblock() {
      </ul></div>
      </div>"#,
         r"Here's a [link][1].
-
 * Bullet
 * Bullet
 * Bullet
@@ -1295,7 +1342,6 @@ fn test_trivial_decorator() {
      </ul></div>
      </div>"#,
         r"Here's a link.
-
 Bullet
 Bullet
 Bullet