diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs index 03bafceea..7b6fe182a 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs @@ -116,6 +116,11 @@ private static void ProcessAppliesToDirective(AppliesToDirective appliesToDirect { var applicableTo = YamlSerialization.Deserialize(yaml); appliesToDirective.AppliesTo = applicableTo; + if (appliesToDirective.AppliesTo.Warnings is null) + return; + foreach (var warning in appliesToDirective.AppliesTo.Warnings) + appliesToDirective.EmitWarning(warning); + applicableTo.Warnings = null; } catch (Exception e) { diff --git a/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs b/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs index f0f241cee..ef618ccad 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs @@ -24,6 +24,8 @@ public record ApplicableTo [YamlMember(Alias = "product")] public ApplicabilityOverTime? Product { get; set; } + public string[]? Warnings { get; set; } + public static ApplicableTo All { get; } = new() { Stack = ApplicabilityOverTime.GenerallyAvailable, @@ -87,6 +89,11 @@ public record ServerlessProjectApplicability public class ApplicableToConverter : IYamlTypeConverter { + private static readonly string[] KnownKeys = + ["stack", "deployment", "serverless", "product", "ece", + "eck", "ess", "self", "elasticsearch", "observability","security" + ]; + public bool Accepts(Type type) => type == typeof(ApplicableTo); public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) @@ -103,7 +110,18 @@ public class ApplicableToConverter : IYamlTypeConverter if (deserialized is not Dictionary { Count: > 0 } dictionary) return null; + var applicableTo = new ApplicableTo(); + var warnings = new List(); + + var keys = dictionary.Keys.OfType().ToArray(); + var oldStyleKeys = keys.Where(k => k.StartsWith(":")).ToList(); + if (oldStyleKeys.Count > 0) + warnings.Add($"Applies block does not use valid yaml keys: {string.Join(", ", oldStyleKeys)}"); + var unknownKeys = keys.Except(KnownKeys).Except(oldStyleKeys).ToList(); + if (unknownKeys.Count > 0) + warnings.Add($"Applies block does not support the following keys: {string.Join(", ", unknownKeys)}"); + if (TryGetApplicabilityOverTime(dictionary, "stack", out var stackAvailability)) applicableTo.Stack = stackAvailability; @@ -119,6 +137,8 @@ public class ApplicableToConverter : IYamlTypeConverter if (TryGetProjectApplicability(dictionary, out var serverless)) applicableTo.Serverless = serverless; + if (warnings.Count > 0) + applicableTo.Warnings = warnings.ToArray(); return applicableTo; } diff --git a/tests/authoring/Applicability/AppliesToDirective.fs b/tests/authoring/Applicability/AppliesToDirective.fs index fb3148618..006c1c70c 100644 --- a/tests/authoring/Applicability/AppliesToDirective.fs +++ b/tests/authoring/Applicability/AppliesToDirective.fs @@ -55,4 +55,30 @@ serverless: Elasticsearch=ApplicabilityOverTime.op_Explicit "beta 9.1.0", Observability=ApplicabilityOverTime.op_Explicit "discontinued 9.2.0" ) - )) \ No newline at end of file + )) + +type ``warns on old syntax`` () = + static let markdown = Setup.Markdown """ +```{applies_to} +:hosted: all +``` +""" + [] + let ``has no errors`` () = markdown |> hasNoErrors + + [] + let ``warns on bad syntax`` () = + markdown |> hasWarning "Applies block does not use valid yaml keys: :hosted" + +type ``warns on invalid keys`` () = + static let markdown = Setup.Markdown """ +```{applies_to} +hosted: all +``` +""" + [] + let ``has no errors`` () = markdown |> hasNoErrors + + [] + let ``warns on bad syntax`` () = + markdown |> hasWarning "Applies block does not support the following keys: hosted"