Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Fix crash (`failwith "tbd - IndirectImage"`) when `Markdown.ToMd` is called on a document containing reference-style images with bracket syntax. The indirect image is now serialised as `![alt](url)` when the reference is resolved, or in bracket notation when it is not. [#1094](https://github.com/fsprojects/FSharp.Formatting/pull/1094)
* Fix `Markdown.ToMd` serialising italic spans with asterisks incorrectly as bold spans. [#1102](https://github.com/fsprojects/FSharp.Formatting/pull/1102)
* Fix `Markdown.ToMd` serialising ordered list items with incorrect numbering and formatting. [#1102](https://github.com/fsprojects/FSharp.Formatting/pull/1102)
* Fix `Markdown.ToMd` not preserving indented code blocks: bare code output was re-parsed as a paragraph. Indented code blocks are now serialised as fenced code blocks, which round-trip correctly.

### Changed
* `fsdocs build` now pre-computes the navigation menu structure (filter/group/sort) once per build rather than once per output page, reducing work from O(nΒ²) to O(n) for sites with n pages. The filesystem check for custom menu templates is also cached per build. [#1129](https://github.com/fsprojects/FSharp.Formatting/pull/1129)
Expand Down
12 changes: 6 additions & 6 deletions src/FSharp.Formatting.Markdown/MarkdownUtils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,15 @@ module internal MarkdownUtils =
yield "-----------------------"
yield ""
| CodeBlock(code = code; fence = fence; language = language) ->
match fence with
| None -> ()
| Some f -> yield f + language
// Indented code blocks (fence = None) are serialised as fenced blocks so
// that the round-trip is valid β€” raw indented code without a '> ' prefix
// or 4-space indent would be parsed as a paragraph, not a code block.
let f = defaultArg fence "```"
yield f + language

yield code

match fence with
| None -> ()
| Some f -> yield f
yield f

yield ""
| ListBlock(Unordered, paragraphsl, _) ->
Expand Down
33 changes: 33 additions & 0 deletions tests/FSharp.Markdown.Tests/Markdown.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1371,3 +1371,36 @@ let ``ToMd round-trip: indirect image with unresolved reference`` () =
let result = Markdown.ToMd(doc)
// When key is not resolved, should preserve the indirect form
result |> should contain "![alt text][unknown-ref]"

// --------------------------------------------------------------------------------------
// ToMd round-trip: indented code block (fence = None) β€” issue #fix-tomd-indented-codeblock
// --------------------------------------------------------------------------------------

[<Test>]
let ``ToMd round-trip: indented code block is preserved as a code block`` () =
// An indented code block (4-space indent) is serialised as a fenced block to
// guarantee the round-trip: outputting bare code without any fence would cause
// re-parsing to produce a paragraph instead of a code block.
let input = " let x = 1\n let y = 2"
let doc = Markdown.Parse(input)
// The parser should have produced a CodeBlock, not a Paragraph
let cbs =
doc.Paragraphs
|> List.choose (function
| CodeBlock _ as cb -> Some cb
| _ -> None)

cbs |> should haveLength 1
// ToMd should produce a fenced form so the round-trip is valid
let result = Markdown.ToMd(doc, newline = "\n")
result |> should contain "```"
result |> should contain "let x = 1"
result |> should contain "let y = 2"
// The serialised form re-parses to a CodeBlock, not a Paragraph
let doc2 = Markdown.Parse(result)

doc2.Paragraphs
|> List.choose (function
| CodeBlock _ as cb -> Some cb
| _ -> None)
|> should haveLength 1