Extra line breaks added between list items and headings when pasting content

Steps to reproduce

Ask ChatGPT a question, such as

Compare Rust and Go

For easy reproduction of this bug. I have shared the ChatGPT results here : https://chatgpt.com/share/6918cce8-a02c-800b-a343-1a0d8341f03d

Copy the conversation content in Microsoft Edge on Windows 11, and paste it into Obsidian.

Did you follow the troubleshooting guide? [Y/N] Y

Expected result

Here is a file with the extra line breaks manually removed.

Here’s a **clear, technical, no-nonsense comparison of Rust vs Go**, tailored for someone who works with infrastructure, backend systems, and performance-sensitive tools like you do.

---
# 🔥 **Rust vs Go: A Practical Comparison**

Both languages target system-level and backend development, but they are optimized for _very_ different design goals. Here’s how they compare across the dimensions that actually matter in real-world engineering.

---
## 🧠 **Philosophy**

### **Rust**
- Zero-cost abstractions, maximum control.
- Guarantees memory safety _at compile time_.
- Focuses on correctness, performance, and low-level control.    
- Prefers explicitness; avoids hidden behavior or magic.
### **Go**
- Simplicity and speed of development above all else.
- Garbage-collected, opinionated, minimalistic.
- Designed for large distributed systems and teams.
- Focuses on readability and maintainability.
---
# ⚙️ **Performance**
### **Rust**
- As fast as C/C++ in many workloads.
- Zero-cost abstractions, no GC pauses, fine-grained control.
- Better throughput for CPU-heavy tasks, async event loops, crypto, compilers, image processing, etc.
### **Go**
- Still fast, but GC can introduce latency (though much improved).
- More overhead in tight loops, high-CPU workloads, or where memory layout matters.
- Fantastic for IO-bound server workloads.

**Verdict:** Rust wins for raw performance and predictable latency; Go wins for most web servers.

---
# 🛑 **Memory Safety & Concurrency Model**

### **Rust**
- Borrow checker ensures no data races at compile time.
- Fearless concurrency: if it compiles, it’s safe.
- But learning the ownership/borrowing model can be _hard_.
### **Go**
- Simple concurrency model via goroutines + channels.
- GC removes memory-management burden.
- But data races are still possible; requires discipline + `-race` detector.

**Verdict:** Rust = safety; Go = simplicity.

---
# 🧵 **Async Model**

### **Rust**
- `async/await` is powerful but… complicated.
- Ecosystem fragmented (`tokio`, `async-std`, `smol`).
- Exceptional performance for async IO.
### **Go**
- Goroutines are lightweight threads with synchronous syntax.
- No async/await ceremony.
- Much easier to write and reason about.

**Verdict:** Go’s concurrency model is one of the best in all of programming.

---
# 📦 **Ecosystem & Tooling**

### **Rust**
- Cargo is arguably the best build system + package manager in any language.
- Excellent compiler messages.
- Strong library ecosystem for:
    - systems programming
    - cryptography
    - WASM
    - embedded
- Weaker for high-level web frameworks or enterprise-y stuff.
### **Go**
- Standard library is shockingly complete.
- Tools (formatter, linter, vet, benchmarks) built in.
- The ecosystem revolves around cloud/server workflows:
    - HTTP servers
    - microservices
    - DevOps tooling
    - CLIs
- Less pleasant for low-level binary manipulation, unsafe code, custom allocators, etc. 

---
# ⏱️ **Developer Experience**
### **Rust**

Pros:
- Beautiful types
- Strong guarantees
- Compiler guides you

Cons:
- Steeper learning curve
- Compile times can be slow
- More code to write for simple tasks
### **Go**

Pros:
- Dead simple
- Very fast builds
- Easy to onboard new engineers
- “It just works”

Cons:
- Too simple for some (error handling boilerplate)
- Limited generics (improving)
- Fewer safety guarantees

---
# 🧰 **Use Cases**

### **Rust is best for:**

- High-performance servers    
- Network proxies, load balancers (e.g., Linkerd, Fly.io, vector.dev)
- Cryptography
- Embedded systems
- CLI tools needing speed + safety
- Replacing C/C++ libraries
- WASM

### **Go is best for:**
- Cloud native services (Kubernetes, Docker, Terraform, Vault)
- Backend APIs
- DevOps tooling
- Distributed systems
- Anything with high IO / concurrency
- Team projects with mixed skill levels

---
# 🥇 **Which Should YOU Use?**

Given your background (Python + infra + security + CLIs + backend tooling):

### **Choose Rust if:**
- You want max performance + safety.
- You’re building a performance-critical CLI or backend service.
- You’re replacing or interfacing with C/C++.
- You want deterministic latency for networking/security tools.

### **Choose Go if:**
- You want to ship quickly.
- You’re building distributed infra tooling or microservices.
- You need concurrency without pain.
- You want something maintainable by a broader engineering team.

---
# ✨ Summary Table

| Feature        | Rust                     | Go                        |
| -------------- | ------------------------ | ------------------------- |
| Performance    | ⭐⭐⭐⭐⭐                    | ⭐⭐⭐⭐                      |
| Memory Safety  | ⭐⭐⭐⭐⭐                    | ⭐⭐⭐                       |
| Concurrency    | ⭐⭐⭐⭐                     | ⭐⭐⭐⭐⭐                     |
| Compile Times  | ⭐⭐                       | ⭐⭐⭐⭐⭐                     |
| Learning Curve | Hard                     | Easy                      |
| Ecosystem      | Systems-focused          | Cloud/server-focused      |
| Best For       | Low-level, perf-critical | Distributed systems, APIs |

---
If you want, I can also compare:  
✔ Rust async vs Go goroutines  
✔ Rust vs Go for CLI tools  
✔ Rust vs Go for Kubernetes-friendly microservices  
✔ Example code in both languages side-by-side  
✔ Performance benchmarks for your specific workload

Just tell me what angle you want next.

Actual result

Here is the original pasted content with no other changes.

Here’s a **clear, technical, no-nonsense comparison of Rust vs Go**, tailored for someone who works with infrastructure, backend systems, and performance-sensitive tools like you do.

---

# 🔥 **Rust vs Go: A Practical Comparison**

Both languages target system-level and backend development, but they are optimized for _very_ different design goals. Here’s how they compare across the dimensions that actually matter in real-world engineering.

---

## 🧠 **Philosophy**

### **Rust**

- Zero-cost abstractions, maximum control.
    
- Guarantees memory safety _at compile time_.
    
- Focuses on correctness, performance, and low-level control.
    
- Prefers explicitness; avoids hidden behavior or magic.
    

### **Go**

- Simplicity and speed of development above all else.
    
- Garbage-collected, opinionated, minimalistic.
    
- Designed for large distributed systems and teams.
    
- Focuses on readability and maintainability.
    

---

# ⚙️ **Performance**

### **Rust**

- As fast as C/C++ in many workloads.
    
- Zero-cost abstractions, no GC pauses, fine-grained control.
    
- Better throughput for CPU-heavy tasks, async event loops, crypto, compilers, image processing, etc.
    

### **Go**

- Still fast, but GC can introduce latency (though much improved).
    
- More overhead in tight loops, high-CPU workloads, or where memory layout matters.
    
- Fantastic for IO-bound server workloads.
    

**Verdict:** Rust wins for raw performance and predictable latency; Go wins for most web servers.

---

# 🛑 **Memory Safety & Concurrency Model**

### **Rust**

- Borrow checker ensures no data races at compile time.
    
- Fearless concurrency: if it compiles, it’s safe.
    
- But learning the ownership/borrowing model can be _hard_.
    

### **Go**

- Simple concurrency model via goroutines + channels.
    
- GC removes memory-management burden.
    
- But data races are still possible; requires discipline + `-race` detector.
    

**Verdict:** Rust = safety; Go = simplicity.

---

# 🧵 **Async Model**

### **Rust**

- `async/await` is powerful but… complicated.
    
- Ecosystem fragmented (`tokio`, `async-std`, `smol`).
    
- Exceptional performance for async IO.
    

### **Go**

- Goroutines are lightweight threads with synchronous syntax.
    
- No async/await ceremony.
    
- Much easier to write and reason about.
    

**Verdict:** Go’s concurrency model is one of the best in all of programming.

---

# 📦 **Ecosystem & Tooling**

### **Rust**

- Cargo is arguably the best build system + package manager in any language.
    
- Excellent compiler messages.
    
- Strong library ecosystem for:
    
    - systems programming
        
    - cryptography
        
    - WASM
        
    - embedded
        
- Weaker for high-level web frameworks or enterprise-y stuff.
    

### **Go**

- Standard library is shockingly complete.
    
- Tools (formatter, linter, vet, benchmarks) built in.
    
- The ecosystem revolves around cloud/server workflows:
    
    - HTTP servers
        
    - microservices
        
    - DevOps tooling
        
    - CLIs
        
- Less pleasant for low-level binary manipulation, unsafe code, custom allocators, etc.
    

---

# ⏱️ **Developer Experience**

### **Rust**

Pros:

- Beautiful types
    
- Strong guarantees
    
- Compiler guides you
    

Cons:

- Steeper learning curve
    
- Compile times can be slow
    
- More code to write for simple tasks
    

### **Go**

Pros:

- Dead simple
    
- Very fast builds
    
- Easy to onboard new engineers
    
- “It just works”
    

Cons:

- Too simple for some (error handling boilerplate)
    
- Limited generics (improving)
    
- Fewer safety guarantees
    

---

# 🧰 **Use Cases**

### **Rust is best for:**

- High-performance servers
    
- Network proxies, load balancers (e.g., Linkerd, Fly.io, vector.dev)
    
- Cryptography
    
- Embedded systems
    
- CLI tools needing speed + safety
    
- Replacing C/C++ libraries
    
- WASM
    

### **Go is best for:**

- Cloud native services (Kubernetes, Docker, Terraform, Vault)
    
- Backend APIs
    
- DevOps tooling
    
- Distributed systems
    
- Anything with high IO / concurrency
    
- Team projects with mixed skill levels
    

---

# 🥇 **Which Should YOU Use?**

Given your background (Python + infra + security + CLIs + backend tooling):

### **Choose Rust if:**

- You want max performance + safety.
    
- You’re building a performance-critical CLI or backend service.
    
- You’re replacing or interfacing with C/C++.
    
- You want deterministic latency for networking/security tools.
    

### **Choose Go if:**

- You want to ship quickly.
    
- You’re building distributed infra tooling or microservices.
    
- You need concurrency without pain.
    
- You want something maintainable by a broader engineering team.
    

---

# ✨ Summary Table

|Feature|Rust|Go|
|---|---|---|
|Performance|⭐⭐⭐⭐⭐|⭐⭐⭐⭐|
|Memory Safety|⭐⭐⭐⭐⭐|⭐⭐⭐|
|Concurrency|⭐⭐⭐⭐|⭐⭐⭐⭐⭐|
|Compile Times|⭐⭐|⭐⭐⭐⭐⭐|
|Learning Curve|Hard|Easy|
|Ecosystem|Systems-focused|Cloud/server-focused|
|Best For|Low-level, perf-critical|Distributed systems, APIs|

---

If you want, I can also compare:  
✔ Rust async vs Go goroutines  
✔ Rust vs Go for CLI tools  
✔ Rust vs Go for Kubernetes-friendly microservices  
✔ Example code in both languages side-by-side  
✔ Performance benchmarks for your specific workload

Just tell me what angle you want next.

The resulting markdown has extra spaces above headings and after list items.

Environment

SYSTEM INFO:
Obsidian version: v1.10.3
Installer version: v1.9.14
Operating system: Windows 11 Pro 10.0.26100
Login status: logged in
Language: en
Catalyst license: none
Insider build toggle: off
Live preview: on
Base theme: adapt to system
Community theme: none
Snippets enabled: 0
Restricted mode: on

RECOMMENDATIONS:
none

Microsoft Edge 142.0.3595.80 (Official build) (64-bit)


Additional information

Note: I found the thread Copy-And-Pasting Headers From ChatGPT -> formatting mess - #12 by rigmarole in the Help category, but most of that thread doesn’t describe the issue well, although this post in the thread does a decent job, these were not bug reports.

Issues with extra line breaks in lists in from non-ChatGPT content was mentioned 4 years ago, but again, not as a bug: Fixed issue with "Pasting formatted text gives double line breaks between list items".

Really wishing I could edit my post to fix all of the typos I’m reading now, including in the title!

As a workaround, the “Text format” community plugin can clean up extra newlines.

I fixed typos in the title. I didn’t notice any in the body when skimming, but I moved the note about other posts down to the Additional Info section. I also removed the code formatting from the links, thinking Discourse might allow them because I was editing (it did).

ChatGPT is writing:

<li>
<p> TEXT HERE</p>
</li>

Rather than just:

<li> TEXT HERE </li>

Linter can be used to automatically lint ChatGPT’s output.

1 Like

Oh, interesting. So the extra spaces are correct.

Lostinbase’s “just” link includes the explanation, but it’s some distance down in the section, so here is a fragment link directly to it: “If list items are separated by blank lines”.

ChatGPT says you can instruct it to not add <p> elements to lists:

You’re right that <li> elements normally shouldn’t contain <p> tags unless the list item truly contains multiple paragraphs. Many HTML style guides and linters recommend avoiding <p> inside <li> unless necessary.

So why does ChatGPT sometimes output <p> inside <li>?

Here are the main reasons:

1. My formatting engine tries to keep paragraph structure

When I generate text, I often break content into paragraphs for readability. When converting that text into HTML lists, I may wrap those paragraphs in <p> tags—even inside <li> elements—because I’m preserving paragraph breaks rather than optimizing for minimal markup.

2. HTML technically allows <p> inside <li>

Although not always stylistically preferred, the HTML specification does allow block-level elements—including <p>—inside list items. So the output is valid, even if not ideal.

3. Automatic Markdown-to-HTML conversion

If my internal Markdown renderer sees blank lines inside a list item, it converts them into separate <p> tags. For example:

- First sentence.

  Second sentence.

becomes:

<li>
  <p>First sentence.</p>
  <p>Second sentence.</p>
</li>

Even if you intended a single continuous list item, the blank line forces paragraph tags.

4. Lack of instruction from the user

Unless users explicitly request “no <p> tags inside <li>,” I default to the most semantically safe and readable structure, even if more verbose.


If you prefer <li> without <p>

Just tell me something like:

“Please format lists without <p> tags inside <li>.”

and I’ll follow that rule in all subsequent outputs within the same conversation.


If you’d like, I can show you how to configure a preferred HTML style or help you rewrite HTML to remove <p> wrappers automatically.

ok, create a list of ten random items but format the list without <p> tags inside <li>

Here you go — 10 random items, formatted exactly as requested, with no <p> tags inside <li>:

<ul>
  <li>Meteor-shaped stress ball</li>
  <li>Ceramic owl figurine</li>
  <li>Neon-green keychain whistle</li>
  <li>Foldable pocket magnifier</li>
  <li>Miniature woven basket</li>
  <li>Hexagonal dice tray</li>
  <li>Silver-ink calligraphy pen</li>
  <li>Magnetic hourglass</li>
  <li>Amber-colored glass bead</li>
  <li>Portable wind-up radio</li>
</ul>

Convert that list to Markdown:

Here is the same list converted to Markdown, with no extra paragraph spacing:

- Meteor-shaped stress ball
- Ceramic owl figurine
- Neon-green keychain whistle
- Foldable pocket magnifier
- Miniature woven basket
- Hexagonal dice tray
- Silver-ink calligraphy pen
- Magnetic hourglass
- Amber-colored glass bead
- Portable wind-up radio

You can also ask CGPT to output a conversation as Markdown.

2 Likes

We have had a few of these BR and everytime we looked the extra lines were present in the HTML that ChatGPT (or the other app) put on the clipboard.

That explains the list. But what about the extra line break added above the headings?

There are <hr> tags separating the sections, but I don’t see a <br> or anything like that above the headers.

You can, but sometimes it takes a few prompts to get it to do that.

I told it not to do that, and it said that it updated its saved memory, which is supposed to persist across chats, but when I asked for a list of animals, it claimed that it gave me a list without a <p>, put did it anyway, and when I called that out, it said in generated a list as plaintext markdown, but rendered the same HTML anyway. so ChatGPT will often tell you it has done things when it has not.

For what it’s worth, Microsoft Word did not add extra spaces/line breaks when pasting copied ChatGPT content, but lost all heading structure, and just made the headings bold text.

It turns out an extra line break is being added for any content after an<hr>tag, not just headings.

For what it’s worth, in the original post ChatGPT’s heading and hr spacing looks more normal (and consistent) to me than the more condensed example with the line breaks manually removed. The only oddity I see in ChatGPT’s version besides the loose list is the extra blank line above the “Go” heading (which follows a list, so might be an artifact of that). I know some people prefer to avoid all the line breaks they can, but I would expect automatically produced Markdown to lean toward separating things with blank lines (because it’s more consistent and less likely to trigger edge cases in rendering).

I agree about the spacing. my example wasn’t consistent because I did it by hand and did a terrible job at it. :sweat_smile:

So really, I guess the only thing that needs fixed is the list artifacts.