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
15 changes: 11 additions & 4 deletions src/FSharp.Formatting.Markdown/MarkdownUtils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,19 @@ module internal MarkdownUtils =
let rec formatParagraph (ctx: FormattingContext) paragraph =
[ match paragraph with
| LatexBlock(env, lines, _) ->
yield sprintf "\\begin{%s}" env
// Single-line equation blocks are rendered with the compact $$...$$ notation
// (which is also valid markdown and what most authors write). Multi-line or
// non-standard environments keep the \begin{env}...\end{env} form.
if env = "equation" && lines.Length = 1 then
yield sprintf "$$%s$$" lines.[0]
else
yield sprintf "\\begin{%s}" env

for line in lines do
yield line
for line in lines do
yield line

yield sprintf "\\end{%s}" env

yield sprintf "\\end{%s}" env
yield ""

| Heading(n, spans, _) ->
Expand Down
91 changes: 91 additions & 0 deletions tests/FSharp.Markdown.Tests/Markdown.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1371,3 +1371,94 @@ 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 additional coverage: headings, nested structures, LaTeX display math, inline code
// --------------------------------------------------------------------------------------

[<Test>]
let ``ToMd preserves heading level 4`` () =
"#### Heading Four" |> toMd |> shouldEqual "#### Heading Four"

[<Test>]
let ``ToMd preserves heading level 5`` () =
"##### Heading Five" |> toMd |> shouldEqual "##### Heading Five"

[<Test>]
let ``ToMd preserves heading level 6`` () =
"###### Heading Six" |> toMd |> shouldEqual "###### Heading Six"

[<Test>]
let ``ToMd preserves emphasis inside a heading`` () =
let result = "## Hello *world*" |> toMd
result |> should contain "## Hello *world*"

[<Test>]
let ``ToMd preserves strong text inside a heading`` () =
let result = "## Hello **world**" |> toMd
result |> should contain "## Hello **world**"

[<Test>]
let ``ToMd preserves LaTeX display math`` () =
let md = "$$E = mc^2$$"
let result = toMd md
result |> should contain "$$E = mc^2$$"

[<Test>]
let ``ToMd preserves inline code containing special chars`` () =
let md = "Use `a + b = c` inline."
let result = toMd md
result |> should contain "`a + b = c`"

[<Test>]
let ``ToMd preserves nested unordered list`` () =
// Outer list item containing an inner list
let md = "* outer\n\n * inner"
let result = toMd md
result |> should contain "outer"
result |> should contain "inner"

[<Test>]
let ``ToMd preserves a nested blockquote`` () =
// A blockquote that itself contains a blockquote
let md = "> > inner quote"
let result = toMd md
result |> should contain "> "
result |> should contain "inner quote"
// The inner quote marker should appear in the output (two levels of '>')
result |> should contain "> >"

[<Test>]
let ``ToMd preserves emphasis inside a blockquote`` () =
let md = "> *italic text*"
let result = toMd md
result |> should contain "> "
result |> should contain "*italic text*"

[<Test>]
let ``ToMd preserves inline code inside a blockquote`` () =
let md = "> use `printf` here"
let result = toMd md
result |> should contain "> "
result |> should contain "`printf`"

[<Test>]
let ``ToMd preserves a code block without language`` () =
let md = "```\nsome code\n```"
let result = toMd md
result |> should contain "some code"
result |> should contain "```"

[<Test>]
let ``ToMd preserves horizontal rule (dash variant)`` () =
let md = "---"
let result = toMd md
result |> should contain "---"

[<Test>]
let ``ToMd preserves a link with a title`` () =
// Title attribute is allowed in Markdown links
let md = "[FSharp](https://fsharp.org \"F# home\")"
let result = toMd md
result |> should contain "[FSharp]("
result |> should contain "https://fsharp.org"