Skip to content

Commit 1507285

Browse files
github-actions[bot]Repo AssistCopilotdsyme
authored
Fix #693: add uppercase ConditionalDefines and strip marker lines from LiterateCode (#999)
- Add outputKind.Extension.ToUpperInvariant() to ConditionalDefines so both '#if HTML' and '#if html' (and equivalents for other output kinds) are supported - Strip '#if SYMBOL' / '#endif // SYMBOL' marker lines from LiterateCode Line list before syntax-highlighting so they do not appear in formatted output - Add tests covering both fixes Co-authored-by: Repo Assist <repo-assist@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Don Syme <dsyme@users.noreply.github.com>
1 parent 88c4938 commit 1507285

4 files changed

Lines changed: 110 additions & 2 deletions

File tree

RELEASE_NOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Fixed
66
* Improve error message when a named code snippet is not found (e.g. `(*** include:name ***)` with undefined name now reports the missing name clearly). [#982](https://github.com/fsprojects/FSharp.Formatting/pull/982)
7+
* Add uppercase output kind extension (e.g. `HTML`, `IPYNB`) to `ConditionalDefines` so that `#if HTML` and `(*** condition: HTML ***)` work alongside their lowercase variants. [#693](https://github.com/fsprojects/FSharp.Formatting/issues/693)
8+
* Strip `#if SYMBOL` / `#endif // SYMBOL` marker lines from `LiterateCode` source before syntax-highlighting so they do not appear in formatted output. [#693](https://github.com/fsprojects/FSharp.Formatting/issues/693)
79

810
### Changed
911
* Update FCS to 43.10.100. [#935](https://github.com/fsprojects/FSharp.Formatting/pull/966)

src/FSharp.Formatting.Literate/Literate.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type Literate private () =
3030
mdlinkResolver
3131
tokenKindToCss
3232
=
33-
let defines = [ outputKind.Extension ]
33+
let defines = [ outputKind.Extension; outputKind.Extension.ToUpperInvariant() ]
3434

3535
{ Substitutions = substitutions
3636
GenerateLineNumbers = defaultArg lineNumbers true

src/FSharp.Formatting.Literate/Transformations.fs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,18 @@ module internal Transformations =
553553
let replaceLiterateParagraphs ctx (doc: LiterateDocument) =
554554
let codes = doc.Paragraphs |> List.collect collectLiterateCode
555555

556-
let snippets = [| for _, (lines, _) in codes -> Snippet("", lines) |]
556+
// Strip #if SYMBOL / #endif // SYMBOL marker lines from code before syntax-highlighting,
557+
// so that they don't appear in the formatted output.
558+
let markerLines =
559+
ctx.ConditionalDefines
560+
|> List.collect (fun sym -> [ sprintf "#if %s" sym; sprintf "#endif // %s" sym ])
561+
|> Set.ofList
562+
563+
let stripDefineLines (lines: Line list) =
564+
lines
565+
|> List.filter (fun (Line(originalLine, _)) -> not (markerLines.Contains(originalLine.Trim())))
566+
567+
let snippets = [| for _, (lines, _) in codes -> Snippet("", stripDefineLines lines) |]
557568

558569
// Format all snippets and build lookup dictionary for parameters
559570
let formatted =

tests/FSharp.Literate.Tests/LiterateTests.fs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,101 @@ let ``Script transforms to markdown`` () =
17681768
md |> shouldContainText "Another [hyperlink](simple2.md)"
17691769
md |> shouldContainText "let hello ="
17701770

1771+
[<Test>]
1772+
let ``condition: HTML uppercase is included in HTML output and excluded from Pynb output`` () =
1773+
let content =
1774+
"""
1775+
let commonCode = 1
1776+
(*** condition: HTML ***)
1777+
let htmlOnlyCode = 2
1778+
let moreCode = 3
1779+
"""
1780+
1781+
let doc = Literate.ParseScriptString(content, "C" </> "test.fsx")
1782+
let html = Literate.ToHtml(doc)
1783+
let pynb = Literate.ToPynb(doc)
1784+
1785+
// (*** condition: HTML ***) with uppercase should be included in HTML output (fix 1)
1786+
html |> shouldContainText "htmlOnlyCode"
1787+
// And excluded from Pynb output
1788+
pynb |> shouldNotContainText "htmlOnlyCode"
1789+
1790+
[<Test>]
1791+
let ``condition: html lowercase is still included in HTML output`` () =
1792+
let content =
1793+
"""
1794+
let commonCode = 1
1795+
(*** condition: html ***)
1796+
let htmlOnlyCode = 2
1797+
let moreCode = 3
1798+
"""
1799+
1800+
let doc = Literate.ParseScriptString(content, "C" </> "test.fsx")
1801+
let html = Literate.ToHtml(doc)
1802+
let pynb = Literate.ToPynb(doc)
1803+
1804+
// (*** condition: html ***) with lowercase should still be included in HTML output
1805+
html |> shouldContainText "htmlOnlyCode"
1806+
// And excluded from Pynb output
1807+
pynb |> shouldNotContainText "htmlOnlyCode"
1808+
1809+
[<Test>]
1810+
let ``#if HTML and #endif // HTML marker lines are stripped from HTML LiterateCode output`` () =
1811+
let content =
1812+
"""
1813+
let alwaysVisible = 1
1814+
#if HTML
1815+
let insideHtmlBlock = 2
1816+
#endif // HTML
1817+
let alsoAlwaysVisible = 3
1818+
"""
1819+
1820+
let doc = Literate.ParseScriptString(content, "C" </> "test.fsx")
1821+
let html = Literate.ToHtml(doc)
1822+
1823+
// The #if HTML / #endif // HTML marker lines themselves should not appear in HTML output.
1824+
// They would appear as <span class="pp">#if</span> tokens before this fix.
1825+
html |> shouldNotContainText ">#if<"
1826+
html |> shouldNotContainText ">#endif<"
1827+
1828+
[<Test>]
1829+
let ``#if HTML and #endif // HTML marker lines are not in Fsx but code inside is present`` () =
1830+
let content =
1831+
"""
1832+
let alwaysVisible = 1
1833+
#if HTML
1834+
let insideHtmlBlock = 2
1835+
#endif // HTML
1836+
let alsoAlwaysVisible = 3
1837+
"""
1838+
1839+
let doc = Literate.ParseScriptString(content, "C" </> "test.fsx")
1840+
let fsx = Literate.ToFsx(doc)
1841+
1842+
// The code inside the #if HTML block does appear as-is in fsx output
1843+
// (only #if FSX / #endif // FSX marker lines are stripped for fsx output)
1844+
fsx |> shouldContainText "insideHtmlBlock"
1845+
1846+
[<Test>]
1847+
let ``#if IPYNB and #endif // IPYNB marker lines are stripped from Pynb LiterateCode output`` () =
1848+
let content =
1849+
"""
1850+
let alwaysVisible = 1
1851+
#if IPYNB
1852+
let insideIpynbBlock = 2
1853+
#endif // IPYNB
1854+
let alsoAlwaysVisible = 3
1855+
"""
1856+
1857+
let doc = Literate.ParseScriptString(content, "C" </> "test.fsx")
1858+
let pynb = Literate.ToPynb(doc)
1859+
1860+
// The marker lines should not appear in Pynb output
1861+
pynb |> shouldNotContainText "#if IPYNB"
1862+
pynb |> shouldNotContainText "#endif // IPYNB"
1863+
// But the code inside should be present
1864+
pynb |> shouldContainText "insideIpynbBlock"
1865+
17711866
// --------------------------------------------------------------------------------------
17721867
// Emoji in FSX comments → HTML (Issue #964)
17731868
// These tests verify that emoji characters are preserved throughout the full

0 commit comments

Comments
 (0)