Skip to content

Commit e276ebc

Browse files
[Repo Assist] fix: use ctx.Newline in ToMd table rows and ToFsx output comments (#1195)
* fix: use ctx.Newline in ToMd table rows and ToFsx output comments Previously, the TableBlock serialiser in MarkdownUtils.fs joined all data rows into a single string using String.concat "\\n" (hardcoded Unix newline), and then emitted a literal "\n" string as the trailing blank line sentinel. On Windows (ctx.Newline = "\r\n") this produced mixed line endings in the ToMd output. This commit refactors the TableBlock case to yield each data row as a separate string (consistent with every other paragraph type), so the outer String.concat newline in formatAsMarkdown applies the correct separator. The trailing blank line now uses the standard "" empty-line sentinel. FsxFormatting.fs had the same kind of issue: the (\* output: ...*) comment wrapper used a literal "\n" to open the comment block. It now uses ctx.Newline so both the opening and the content use consistent line endings. Two new unit tests cover the table row count and the Windows regression. 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>
1 parent e090b43 commit e276ebc

4 files changed

Lines changed: 41 additions & 17 deletions

File tree

RELEASE_NOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* Replace `Enumerable.Cast<XAttribute>` (LINQ) with `Seq.cast<XAttribute>` (idiomatic F#) in `MarkdownUtils.fs`, removing the `open System.Linq` import.
1212

1313
### Fixed
14+
* Fix `Markdown.ToMd` serialising table data rows with a hardcoded `\n` line separator instead of the configured newline. On Windows (where `Environment.NewLine` is `\r\n`) this produced mixed line endings in the output. Each data row is now yielded separately, consistent with how every other paragraph type works. The trailing blank line after a table was also emitting a literal `"\n"` string instead of the standard `""` empty-line sentinel.
15+
* Fix `Markdown.ToFsx` hardcoding a `\n` newline in the `(* output: ...)` comment wrapper around code-cell outputs. The configured `ctx.Newline` is now used, ensuring consistent line endings on Windows.
1416
* Fix `Markdown.ToMd` silently dropping YAML frontmatter when serialising a parsed `MarkdownDocument` back to Markdown text. Frontmatter is now preserved with its `---` delimiters.
1517
* 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.
1618
* 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`.

src/FSharp.Formatting.Markdown/FsxFormatting.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ let rec formatParagraphs ctx paragraphs =
6262
code2
6363
+ (match codeOutput with
6464
| [] -> ""
65-
| _out -> "(* output: \n" + output + "*)")
65+
| _out -> "(* output: " + ctx.Newline + output + "*)")
6666
| Choice2Of2 markdown ->
6767
"(**"
6868
+ ctx.Newline

src/FSharp.Formatting.Markdown/MarkdownUtils.fs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -268,22 +268,21 @@ module internal MarkdownUtils =
268268
let replaceEmptyWith x s =
269269
if System.String.IsNullOrWhiteSpace s then x else Some s
270270

271-
yield
272-
[ for r in rows do
273-
[ for ps in r do
274-
let x =
275-
[ for p in ps do
276-
yield
277-
formatParagraph ctx p
278-
|> Seq.choose (replaceEmptyWith (Some ""))
279-
|> String.concat "" ]
280-
281-
yield x |> Seq.choose (replaceEmptyWith (Some "")) |> String.concat "<br />" ]
282-
|> Seq.choose (replaceEmptyWith (Some "&#32;"))
283-
|> String.concat " | " ]
284-
|> String.concat "\n"
285-
286-
yield "\n"
271+
for r in rows do
272+
yield
273+
[ for ps in r do
274+
let x =
275+
[ for p in ps do
276+
yield
277+
formatParagraph ctx p
278+
|> Seq.choose (replaceEmptyWith (Some ""))
279+
|> String.concat "" ]
280+
281+
yield x |> Seq.choose (replaceEmptyWith (Some "")) |> String.concat "<br />" ]
282+
|> Seq.choose (replaceEmptyWith (Some "&#32;"))
283+
|> String.concat " | "
284+
285+
yield ""
287286

288287
| OutputBlock(output, "text/html", _executionCount) ->
289288
yield (output.Trim())

tests/FSharp.Markdown.Tests/Markdown.fs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,29 @@ let ``ToMd handles a table`` () =
14061406
result |> should contain "A"
14071407
result |> should contain "B"
14081408

1409+
[<Test>]
1410+
let ``ToMd table rows each appear on their own line`` () =
1411+
// Previously, all data rows were joined into one string with a hardcoded "\n",
1412+
// which produced a single yield item. Now each row is yielded separately so the
1413+
// caller's newline is used. Verify that each row appears on a distinct line.
1414+
let md = "H1 | H2\n--- | ---\nR1C1 | R1C2\nR2C1 | R2C2"
1415+
let result = Markdown.ToMd(Markdown.Parse(md, newline = "\n"), newline = "\n")
1416+
let lines = result.Split('\n') |> Array.filter (fun s -> s.Trim() <> "")
1417+
// Expect: header row, separator row, two data rows
1418+
lines |> should haveLength 4
1419+
1420+
[<Test>]
1421+
let ``ToMd table row count is correct when Windows newline is used`` () =
1422+
// Regression: rows were previously joined with a hardcoded "\n" regardless of ctx.Newline,
1423+
// so on Windows the data section was a single element with embedded Unix newlines.
1424+
let md = "H1 | H2\n--- | ---\nR1C1 | R1C2\nR2C1 | R2C2"
1425+
let result = Markdown.ToMd(Markdown.Parse(md, newline = "\r\n"), newline = "\r\n")
1426+
// All line separators must be \r\n (no stray \n inside the result)
1427+
result |> should not' (contain "\r\n\n")
1428+
result |> should not' (contain "\n\r\n")
1429+
result |> should contain "R1C1"
1430+
result |> should contain "R2C1"
1431+
14091432
[<Test>]
14101433
let ``ToMd handles empty document`` () = "" |> toMd |> shouldEqual ""
14111434

0 commit comments

Comments
 (0)