Fix frontmatter parsing for quote workflow
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
4fc91cec3e
commit
ed51e62b29
3 changed files with 60 additions and 12 deletions
|
|
@ -2,7 +2,7 @@ namespace Yavsc.Server.Models.Billing;
|
||||||
|
|
||||||
public class FrontmatterOffreResult
|
public class FrontmatterOffreResult
|
||||||
{
|
{
|
||||||
public string Formulaire { get; set; }
|
public string Formulaire { get; set; } = string.Empty;
|
||||||
public string Devis { get; set; }
|
public string Devis { get; set; } = string.Empty;
|
||||||
public string Corps { get; set; } // le Markdown sans l'en-tête
|
public string Corps { get; set; } = string.Empty; // le Markdown sans l'en-tête
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ namespace Yavsc.Server.Services;
|
||||||
|
|
||||||
public static class FrontmatterParser
|
public static class FrontmatterParser
|
||||||
{
|
{
|
||||||
public const string YamlHeader = "---\n";
|
public const string YamlHeader = "---";
|
||||||
public const string YamlSeparator = "\n---";
|
public const string YamlSeparator = "---";
|
||||||
|
|
||||||
private static readonly IDeserializer _deserializer =
|
private static readonly IDeserializer _deserializer =
|
||||||
new DeserializerBuilder()
|
new DeserializerBuilder()
|
||||||
|
|
@ -17,17 +17,23 @@ public static class FrontmatterParser
|
||||||
|
|
||||||
public static FrontmatterOffreResult Parse(string markdown)
|
public static FrontmatterOffreResult Parse(string markdown)
|
||||||
{
|
{
|
||||||
// Le contenu doit commencer par ----
|
ArgumentNullException.ThrowIfNull(markdown);
|
||||||
if (!markdown.TrimStart().StartsWith(YamlHeader, StringComparison.Ordinal))
|
|
||||||
|
var trimmed = markdown.TrimStart();
|
||||||
|
|
||||||
|
if (!trimmed.StartsWith(YamlHeader, StringComparison.Ordinal))
|
||||||
return new FrontmatterOffreResult { Corps = markdown };
|
return new FrontmatterOffreResult { Corps = markdown };
|
||||||
|
|
||||||
var parts = markdown.Substring(YamlHeader.Length).Trim().Split(new[] { YamlSeparator }, 2,
|
var afterOpeningMarker = trimmed[YamlHeader.Length..];
|
||||||
StringSplitOptions.None);
|
var parts = afterOpeningMarker
|
||||||
|
.Split(new[] { "\r\n---", "\n---" }, 2, StringSplitOptions.None);
|
||||||
|
|
||||||
if (parts.Length < 2)
|
if (parts.Length < 2)
|
||||||
return new FrontmatterOffreResult { Corps = markdown };
|
return new FrontmatterOffreResult { Corps = markdown };
|
||||||
var yamlBlock = parts[0];
|
|
||||||
var corps = parts[1];
|
var yamlBlock = parts[0].Trim();
|
||||||
var meta = _deserializer.Deserialize<FrontmatterOffreResult>(yamlBlock);
|
var corps = parts[1].TrimStart();
|
||||||
|
var meta = _deserializer.Deserialize<FrontmatterOffreResult>(yamlBlock) ?? new FrontmatterOffreResult();
|
||||||
meta.Corps = corps;
|
meta.Corps = corps;
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
src/test/Yavsc.Server.Tests/FrontmatterParserTests.cs
Normal file
42
src/test/Yavsc.Server.Tests/FrontmatterParserTests.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
using Yavsc.Server.Services;
|
||||||
|
|
||||||
|
namespace Yavsc.Server.Tests;
|
||||||
|
|
||||||
|
public class FrontmatterParserTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Parse_extracts_formulaire_devis_and_body_for_unix_line_endings()
|
||||||
|
{
|
||||||
|
const string markdown = "---\nformulaire: Prestation Musicale\ndevis: Arrangement Orchestral\n---\n\nContenu du devis\n";
|
||||||
|
|
||||||
|
var result = FrontmatterParser.Parse(markdown);
|
||||||
|
|
||||||
|
Assert.Equal("Prestation Musicale", result.Formulaire);
|
||||||
|
Assert.Equal("Arrangement Orchestral", result.Devis);
|
||||||
|
Assert.Equal("Contenu du devis", result.Corps.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Parse_accepts_windows_line_endings()
|
||||||
|
{
|
||||||
|
const string markdown = "---\r\nformulaire: Prestation Musicale\r\ndevis: Arrangement Orchestral\r\n---\r\n\r\nContenu du devis\r\n";
|
||||||
|
|
||||||
|
var result = FrontmatterParser.Parse(markdown);
|
||||||
|
|
||||||
|
Assert.Equal("Prestation Musicale", result.Formulaire);
|
||||||
|
Assert.Equal("Arrangement Orchestral", result.Devis);
|
||||||
|
Assert.Equal("Contenu du devis", result.Corps.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Parse_returns_original_markdown_when_no_frontmatter_is_present()
|
||||||
|
{
|
||||||
|
const string markdown = "# Hello\n\nThis is plain markdown.";
|
||||||
|
|
||||||
|
var result = FrontmatterParser.Parse(markdown);
|
||||||
|
|
||||||
|
Assert.Equal(string.Empty, result.Formulaire);
|
||||||
|
Assert.Equal(string.Empty, result.Devis);
|
||||||
|
Assert.Equal(markdown, result.Corps);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue