diff --git a/Frontmatter.Test/DelimiterLineTests.cs b/Frontmatter.Test/DelimiterLineTests.cs index 198892b..baa4c9a 100644 --- a/Frontmatter.Test/DelimiterLineTests.cs +++ b/Frontmatter.Test/DelimiterLineTests.cs @@ -184,6 +184,27 @@ public void AddFrontmatter_OpeningDelimiterHasTrailingWhitespaceOrBom_MergesInto Assert.AreEqual($"---{Nl}title: A{Nl}author: B{Nl}---{Nl}Body{Nl}", result); } + [TestMethod] + public void AddFrontmatter_BomPrefixedDocumentWithoutHeader_LeavesNoBomInTheBody() + { + string input = $"# Heading{Nl}{Nl}text{Nl}"; + + string result = Frontmatter.AddFrontmatter(input, new Dictionary { ["title"] = "T" }); + + Assert.AreEqual($"---{Nl}title: T{Nl}---{Nl}# Heading{Nl}{Nl}text{Nl}", result); + Assert.AreEqual($"# Heading{Nl}{Nl}text", Frontmatter.ExtractBody(result)); + } + + [TestMethod] + public void AddFrontmatter_BomPrefixedDocumentOpeningWithBlankLines_LeavesNoBomInTheBody() + { + string input = $"{Nl}{Nl}# Heading{Nl}"; + + string result = Frontmatter.AddFrontmatter(input, new Dictionary { ["title"] = "T" }); + + Assert.AreEqual($"---{Nl}title: T{Nl}---{Nl}# Heading{Nl}", result); + } + [TestMethod] public void HasFrontmatter_DelimiterWithoutLineEnding_IsNotFrontmatter() { diff --git a/Frontmatter/Frontmatter.cs b/Frontmatter/Frontmatter.cs index 76b1f83..1f59f33 100644 --- a/Frontmatter/Frontmatter.cs +++ b/Frontmatter/Frontmatter.cs @@ -496,13 +496,15 @@ private static bool IsFollowOnBlock(string block, List<(int Start, int End)> lin /// Trims a document body for output, dropping the blank lines before its first content line and the /// whitespace after its last. Unlike , it keeps the first content line's /// indentation, so a body that opens with an indented code block or nested list content survives. + /// A leading byte order mark is dropped too: it is not whitespace, so it would otherwise be carried + /// past a newly written header and hide the first line from markdown renderers. /// /// The body to trim. - /// The body without leading blank lines or trailing whitespace. + /// The body without a byte order mark, leading blank lines or trailing whitespace. private static string TrimBody(string body) { - int start = 0; - for (int i = 0; i < body.Length; i++) + int start = OpeningLineStart(body); + for (int i = start; i < body.Length; i++) { char c = body[i]; if (c == '\n')