Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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