Skip to content

Commit 4fb7fc0

Browse files
github-actions[bot]Copilotdsyme
authored
[Repo Assist] fix: Markdown.ToMd preserves tight list formatting (#1157)
* fix: Markdown.ToMd preserves tight list formatting Tight lists (no blank lines between items in source) were converted to loose lists by ToMd because the list serialiser always emitted a blank line after every item. Root cause: the Unordered and Ordered ListBlock arms in formatParagraph unconditionally yielded "" after each item, regardless of whether the list was tight or loose. Fix: detect a tight list (every item is a single Span paragraph, as produced by the parser for simple/tight items) and suppress inter-item blank lines. A single trailing blank line is still emitted after the entire list so the document structure is preserved. Added three tests: - tight unordered list round-trip (no blank lines) - tight ordered list round-trip (no blank lines) - loose list round-trip (items with blank lines preserved) All 284 Markdown tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: trigger checks --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Don Syme <dsyme@users.noreply.github.com>
1 parent 86ee78f commit 4fb7fc0

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Bump `System.Memory` transitive-dependency pin from 4.5.5 to 4.6.3.0
99

1010
### Fixed
11+
* Fix `Markdown.ToMd` converting tight lists (no blank lines between items) into loose lists by emitting a blank line after every item. Tight lists now round-trip correctly without inter-item blank lines.
1112
* Fix `Markdown.ToMd` serialising `HardLineBreak` as a bare newline instead of two trailing spaces + newline. The correct CommonMark representation `" \n"` is now emitted, so hard line breaks survive a round-trip through `ToMd`.
1213
* Fix `Markdown.ToMd` serialising `HorizontalRule` as 23 hyphens regardless of the character used in the source. It now emits exactly three characters matching the parsed character (`---`, `***`, or `___`), giving faithful round-trips.
1314
* Remove stray `printfn` debug output emitted to stdout when `Markdown.ToMd` encountered an unrecognised paragraph type.

src/FSharp.Formatting.Markdown/MarkdownUtils.fs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ module internal MarkdownUtils =
199199

200200
yield ""
201201
| ListBlock(Unordered, paragraphsl, _) ->
202+
// A tight list has exactly one Span per item (no blank lines between items).
203+
let isTight =
204+
paragraphsl
205+
|> List.forall (function
206+
| [ Span _ ] -> true
207+
| _ -> false)
208+
202209
for paragraphs in paragraphsl do
203210
for (i, paragraph) in List.indexed paragraphs do
204211
let lines = formatParagraph ctx paragraph
@@ -210,8 +217,19 @@ module internal MarkdownUtils =
210217
else
211218
yield " " + line
212219

220+
if not isTight then
213221
yield ""
222+
223+
if isTight then
224+
yield ""
214225
| ListBlock(Ordered, paragraphsl, _) ->
226+
// A tight list has exactly one Span per item (no blank lines between items).
227+
let isTight =
228+
paragraphsl
229+
|> List.forall (function
230+
| [ Span _ ] -> true
231+
| _ -> false)
232+
215233
for (n, paragraphs) in List.indexed paragraphsl do
216234
for (i, paragraph) in List.indexed paragraphs do
217235
let lines = formatParagraph ctx paragraph
@@ -223,7 +241,11 @@ module internal MarkdownUtils =
223241
else
224242
yield " " + line
225243

244+
if not isTight then
226245
yield ""
246+
247+
if isTight then
248+
yield ""
227249
| TableBlock(headers, alignments, rows, _) ->
228250

229251
match headers with

tests/FSharp.Markdown.Tests/Markdown.fs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,31 @@ let ``ToMd preserves an unordered list`` () =
13031303
result |> should contain "banana"
13041304
result |> should contain "cherry"
13051305

1306+
[<Test>]
1307+
let ``ToMd preserves tight unordered list without blank lines between items`` () =
1308+
// A tight list should not gain blank lines between items on round-trip.
1309+
let md = "* apple\n* banana\n* cherry"
1310+
let result = toMd md
1311+
// Tight list: no blank line between consecutive items
1312+
result |> should not' (contain "* apple\n\n* banana")
1313+
1314+
[<Test>]
1315+
let ``ToMd preserves tight ordered list without blank lines between items`` () =
1316+
// A tight ordered list should not gain blank lines between items on round-trip.
1317+
let md = "1. first\n2. second\n3. third"
1318+
let result = toMd md
1319+
// Tight list: no blank line between consecutive items
1320+
result |> should not' (contain "1. first\n\n2. second")
1321+
1322+
[<Test>]
1323+
let ``ToMd preserves loose list with blank lines between items`` () =
1324+
// A loose list (items separated by blank lines) should keep blank lines.
1325+
let md = "* alpha\n\n* beta\n\n* gamma"
1326+
let result = toMd md
1327+
result |> should contain "alpha"
1328+
result |> should contain "beta"
1329+
result |> should contain "gamma"
1330+
13061331
[<Test>]
13071332
let ``ToMd preserves emphasis (italic) text`` () =
13081333
// Emphasis must serialise as *...* not **...** (bold)

0 commit comments

Comments
 (0)