From 8387e5402c7ef2b1d6126a9bf15cedf25b6667c4 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 17 Feb 2025 21:10:08 +0100 Subject: [PATCH 1/7] Rework applies blocks to applies_to with new semantics --- docs/syntax/applies.md | 36 ++- .../Myst/Directives/AppliesBlock.cs | 70 +---- .../Myst/Directives/DirectiveHtmlRenderer.cs | 12 +- .../Myst/FrontMatter/Applicability.cs | 171 ++++++++++++ .../Myst/FrontMatter/ApplicableTo.cs | 257 ++++++++++++++++++ .../Myst/FrontMatter/Deployment.cs | 30 +- .../Myst/FrontMatter/FrontMatterParser.cs | 6 +- .../Myst/FrontMatter/ProductAvailability.cs | 62 ----- .../Myst/Settings/StructuredSettings.cs | 2 +- .../Myst/YamlSerialization.cs | 3 + .../Slices/Directives/ApplicableTo.cshtml | 125 +++++++++ .../Slices/Directives/Applies.cshtml | 96 ------- src/Elastic.Markdown/Slices/HtmlWriter.cs | 2 +- src/Elastic.Markdown/Slices/Index.cshtml | 2 +- src/Elastic.Markdown/Slices/_ViewModels.cs | 2 +- .../FrontMatter/ProductConstraintTests.cs | 31 ++- tests/authoring/Availability/ApplyYaml.fs | 179 ++++++++++++ .../Framework/MarkdownDocumentAssertions.fs | 17 +- tests/authoring/authoring.fsproj | 4 + 19 files changed, 825 insertions(+), 282 deletions(-) create mode 100644 src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs create mode 100644 src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs delete mode 100644 src/Elastic.Markdown/Myst/FrontMatter/ProductAvailability.cs create mode 100644 src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml delete mode 100644 src/Elastic.Markdown/Slices/Directives/Applies.cshtml create mode 100644 tests/authoring/Availability/ApplyYaml.fs diff --git a/docs/syntax/applies.md b/docs/syntax/applies.md index e5fc267eb..4208c2c16 100644 --- a/docs/syntax/applies.md +++ b/docs/syntax/applies.md @@ -1,10 +1,16 @@ --- -applies: - stack: ga 8.1 - serverless: tech-preview - hosted: beta 8.1.1 - eck: beta 3.0.2 - ece: unavailable +applies_to: + stack: ga 9.1 + deployment: + eck: ga 9.0 + ess: beta 9.1 + ece: discontinued 9.2.0 + self: unavailable 9.3.0 + serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 + product: coming 9.5, discontinued 9.7 --- # Applies to @@ -14,12 +20,18 @@ Using yaml frontmatter pages can explicitly indicate to each deployment targets ```yaml -applies: - stack: ga 8.1 - serverless: tech-preview - hosted: beta 8.1.1 - eck: beta 3.0.2 - ece: unavailable +applies_to: + stack: ga 9.1 + deployment: + eck: ga 9.0 + ess: beta 9.1 + ece: discontinued 9.2.0 + self: unavailable 9.3.0 + serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 + product: coming 9.5, discontinued 9.7 ``` Its syntax is diff --git a/src/Elastic.Markdown/Myst/Directives/AppliesBlock.cs b/src/Elastic.Markdown/Myst/Directives/AppliesBlock.cs index 799aec1d9..695ab00e8 100644 --- a/src/Elastic.Markdown/Myst/Directives/AppliesBlock.cs +++ b/src/Elastic.Markdown/Myst/Directives/AppliesBlock.cs @@ -12,73 +12,5 @@ public class AppliesBlock(DirectiveBlockParser parser, ParserContext context) : { public override string Directive => "mermaid"; - public Deployment? Deployment { get; private set; } - - public override void FinalizeAndValidate(ParserContext context) - { - if (TryGetAvailability("cloud", out var version)) - { - Deployment ??= new Deployment(); - Deployment.Cloud ??= new CloudManagedDeployment(); - Deployment.Cloud.Serverless = version; - Deployment.Cloud.Hosted = version; - } - if (TryGetAvailability("self", out version)) - { - Deployment ??= new Deployment(); - Deployment.SelfManaged ??= new SelfManagedDeployment(); - Deployment.SelfManaged.Ece = version; - Deployment.SelfManaged.Eck = version; - Deployment.SelfManaged.Stack = version; - } - - if (TryGetAvailability("stack", out version)) - { - Deployment ??= new Deployment(); - Deployment.SelfManaged ??= new SelfManagedDeployment(); - Deployment.SelfManaged.Stack = version; - } - if (TryGetAvailability("ece", out version)) - { - Deployment ??= new Deployment(); - Deployment.SelfManaged ??= new SelfManagedDeployment(); - Deployment.SelfManaged.Ece = version; - } - if (TryGetAvailability("eck", out version)) - { - Deployment ??= new Deployment(); - Deployment.SelfManaged ??= new SelfManagedDeployment(); - Deployment.SelfManaged.Eck = version; - } - if (TryGetAvailability("hosted", out version)) - { - Deployment ??= new Deployment(); - Deployment.Cloud ??= new CloudManagedDeployment(); - Deployment.Cloud.Hosted = version; - } - if (TryGetAvailability("serverless", out version)) - { - Deployment ??= new Deployment(); - Deployment.Cloud ??= new CloudManagedDeployment(); - Deployment.Cloud.Serverless = version; - } - - if (Deployment is null) - this.EmitError("{applies} block with no product availability specified"); - - var index = Parent?.IndexOf(this); - if (Parent is not null && index > 0) - { - var i = index - 1 ?? 0; - var prevSib = Parent[i]; - if (prevSib is not HeadingBlock) - this.EmitError("{applies} should follow a heading"); - } - - bool TryGetAvailability(string key, out ProductAvailability? semVersion) - { - semVersion = null; - return Prop(key) is { } v && ProductAvailability.TryParse(v, out semVersion); - } - } + public override void FinalizeAndValidate(ParserContext context) => this.EmitWarning("{applies} is deprecated, please use the {apply} directive"); } diff --git a/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs b/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs index 9fb5155fc..645a8f459 100644 --- a/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs +++ b/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs @@ -36,8 +36,7 @@ protected override void Write(HtmlRenderer renderer, DirectiveBlock directiveBlo case MermaidBlock mermaidBlock: WriteMermaid(renderer, mermaidBlock); return; - case AppliesBlock appliesBlock: - WriteApplies(renderer, appliesBlock); + case AppliesBlock: //deprecated scheduled for removal return; case FigureBlock imageBlock: WriteFigure(renderer, imageBlock); @@ -189,15 +188,6 @@ private void WriteMermaid(HtmlRenderer renderer, MermaidBlock block) RenderRazorSliceRawContent(slice, renderer, block); } - private void WriteApplies(HtmlRenderer renderer, AppliesBlock block) - { - if (block.Deployment is null || block.Deployment == Deployment.All) - return; - - var slice = Applies.Create(block.Deployment); - RenderRazorSliceNoContent(slice, renderer); - } - private void WriteLiteralIncludeBlock(HtmlRenderer renderer, IncludeBlock block) { if (!block.Found || block.IncludePath is null) diff --git a/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs b/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs new file mode 100644 index 000000000..8efb51ab9 --- /dev/null +++ b/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs @@ -0,0 +1,171 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Elastic.Markdown.Helpers; +using YamlDotNet.Serialization; + +namespace Elastic.Markdown.Myst.FrontMatter; + +[YamlSerializable] +public record ApplicabilityOverTime : IReadOnlyCollection +{ + private readonly IReadOnlyCollection _items; + public ApplicabilityOverTime(Applicability[] items) => _items = items; + + // [version] + public static bool TryParse(string? value, out ApplicabilityOverTime? availability) + { + availability = null; + if (string.IsNullOrWhiteSpace(value) || string.Equals(value.Trim(), "all", StringComparison.InvariantCultureIgnoreCase)) + { + availability = GenerallyAvailable; + return true; + } + + var items = value.Split(','); + var applications = new List(items.Length); + foreach (var item in items) + { + if (Applicability.TryParse(item.Trim(), out var a)) + applications.Add(a); + } + + if (applications.Count == 0) + return false; + + availability = new ApplicabilityOverTime(applications.ToArray()); + return true; + } + + public virtual bool Equals(ApplicabilityOverTime? other) + { + if ((object)this == other) + return true; + + if ((object?)other is null || EqualityContract != other.EqualityContract) + return false; + + var comparer = StructuralComparisons.StructuralEqualityComparer; + return comparer.Equals(_items, other._items); + } + + public override int GetHashCode() + { + var comparer = StructuralComparisons.StructuralEqualityComparer; + return (EqualityComparer.Default.GetHashCode(EqualityContract) * -1521134295) + + comparer.GetHashCode(_items); + } + + + public static explicit operator ApplicabilityOverTime(string b) + { + var productAvailability = TryParse(b, out var version) ? version : null; + return productAvailability ?? throw new ArgumentException($"'{b}' is not a valid applicability string array."); + } + + public static ApplicabilityOverTime GenerallyAvailable { get; } + = new([Applicability.GenerallyAvailable]); + + public override string ToString() + { + if (this == GenerallyAvailable) + return "all"; + var sb = new StringBuilder(); + foreach (var item in _items) + sb.Append(item).Append(", "); + return sb.ToString(); + } + + public IEnumerator GetEnumerator() => _items.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public int Count => _items.Count; +} + +[YamlSerializable] +public record Applicability +{ + public ProductLifecycle Lifecycle { get; init; } + public SemVersion? Version { get; init; } + + public static Applicability GenerallyAvailable { get; } = new() + { + Lifecycle = ProductLifecycle.GenerallyAvailable, + Version = AllVersions.Instance + }; + + public override string ToString() + { + if (this == GenerallyAvailable) + return "all"; + var sb = new StringBuilder(); + var lifecycle = Lifecycle switch + { + ProductLifecycle.TechnicalPreview => "preview", + ProductLifecycle.Beta => "beta", + ProductLifecycle.Development => "dev", + ProductLifecycle.Deprecated => "deprecated", + ProductLifecycle.Coming => "coming", + ProductLifecycle.Discontinued => "discontinued", + ProductLifecycle.Unavailable => "unavailable", + ProductLifecycle.GenerallyAvailable => "ga", + _ => throw new ArgumentOutOfRangeException() + }; + sb.Append(lifecycle); + if (Version is not null && Version != AllVersions.Instance) + sb.Append(" ").Append(Version); + return sb.ToString(); + } + + public static explicit operator Applicability(string b) + { + var productAvailability = TryParse(b, out var version) ? version : TryParse(b + ".0", out version) ? version : null; + return productAvailability ?? throw new ArgumentException($"'{b}' is not a valid applicability string."); + } + + // [version] + public static bool TryParse(string? value, [NotNullWhen(true)] out Applicability? availability) + { + if (string.IsNullOrWhiteSpace(value) || string.Equals(value.Trim(), "all", StringComparison.InvariantCultureIgnoreCase)) + { + availability = GenerallyAvailable; + return true; + } + + var tokens = value.Split(" ", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 1) + { + availability = null; + return false; + } + var lifecycle = tokens[0].ToLowerInvariant() switch + { + "preview" => ProductLifecycle.TechnicalPreview, + "tech-preview" => ProductLifecycle.TechnicalPreview, + "beta" => ProductLifecycle.Beta, + "dev" => ProductLifecycle.Development, + "development" => ProductLifecycle.Development, + "deprecated" => ProductLifecycle.Deprecated, + "coming" => ProductLifecycle.Coming, + "discontinued" => ProductLifecycle.Discontinued, + "unavailable" => ProductLifecycle.Unavailable, + "ga" => ProductLifecycle.GenerallyAvailable, + _ => throw new ArgumentOutOfRangeException(nameof(tokens), tokens, $"Unknown product lifecycle: {tokens[0]}") + }; + + var version = tokens.Length < 2 ? null : tokens[1] switch + { + null => AllVersions.Instance, + "all" => AllVersions.Instance, + "" => AllVersions.Instance, + var t => SemVersionConverter.TryParse(t, out var v) ? v : null + }; + availability = new Applicability { Version = version, Lifecycle = lifecycle }; + return true; + } +} diff --git a/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs b/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs new file mode 100644 index 000000000..32b76c22c --- /dev/null +++ b/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs @@ -0,0 +1,257 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Diagnostics.CodeAnalysis; +using System.Text; +using YamlDotNet.Core; +using YamlDotNet.Core.Events; +using YamlDotNet.Serialization; + +namespace Elastic.Markdown.Myst.FrontMatter; + +[YamlSerializable] +public record ApplicableTo +{ + [YamlMember(Alias = "stack")] + public ApplicabilityOverTime? Stack { get; set; } + + [YamlMember(Alias = "deployment")] + public DeploymentApplicability? Deployment { get; set; } + + [YamlMember(Alias = "serverless")] + public ServerlessProjectApplicability? Serverless { get; set; } + + [YamlMember(Alias = "product")] + public ApplicabilityOverTime? Product { get; set; } + + public static ApplicableTo All { get; } = new() + { + Stack = ApplicabilityOverTime.GenerallyAvailable, + Serverless = ServerlessProjectApplicability.All, + Deployment = DeploymentApplicability.All, + Product = ApplicabilityOverTime.GenerallyAvailable + }; +} + +[YamlSerializable] +public record DeploymentApplicability +{ + [YamlMember(Alias = "self")] + public ApplicabilityOverTime? Self { get; set; } + + [YamlMember(Alias = "ece")] + public ApplicabilityOverTime? Ece { get; set; } + + [YamlMember(Alias = "eck")] + public ApplicabilityOverTime? Eck { get; set; } + + [YamlMember(Alias = "ess")] + public ApplicabilityOverTime? Ess { get; set; } + + public static DeploymentApplicability All { get; } = new() + { + Ece = ApplicabilityOverTime.GenerallyAvailable, + Eck = ApplicabilityOverTime.GenerallyAvailable, + Ess = ApplicabilityOverTime.GenerallyAvailable, + Self = ApplicabilityOverTime.GenerallyAvailable + }; +} + +[YamlSerializable] +public record ServerlessProjectApplicability +{ + [YamlMember(Alias = "elasticsearch")] + public ApplicabilityOverTime? Elasticsearch { get; set; } + + [YamlMember(Alias = "observability")] + public ApplicabilityOverTime? Observability { get; set; } + + [YamlMember(Alias = "security")] + public ApplicabilityOverTime? Security { get; set; } + + /// + /// Returns if all projects share the same applicability + /// + public ApplicabilityOverTime? AllProjects => + Elasticsearch == Observability && Observability == Security + ? Elasticsearch + : null; + + public static ServerlessProjectApplicability All { get; } = new() + { + Elasticsearch = ApplicabilityOverTime.GenerallyAvailable, + Observability = ApplicabilityOverTime.GenerallyAvailable, + Security = ApplicabilityOverTime.GenerallyAvailable + }; +} +public class ApplicableToConverter : IYamlTypeConverter +{ + public bool Accepts(Type type) => type == typeof(ApplicableTo); + + public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) + { + if (parser.TryConsume(out var value)) + { + if (string.IsNullOrWhiteSpace(value.Value)) + return ApplicableTo.All; + if (string.Equals(value.Value, "all", StringComparison.InvariantCultureIgnoreCase)) + return ApplicableTo.All; + } + + var deserialized = rootDeserializer.Invoke(typeof(Dictionary)); + if (deserialized is not Dictionary { Count: > 0 } dictionary) + return null; + + var applicableTo = new ApplicableTo(); + if (TryGetApplicabilityOverTime(dictionary, "stack", out var stackAvailability)) + applicableTo.Stack = stackAvailability; + + if (TryGetApplicabilityOverTime(dictionary, "product", out var productAvailability)) + applicableTo.Product = productAvailability; + + AssignServerless(dictionary, applicableTo); + AssignDeploymentType(dictionary, applicableTo); + + if (TryGetDeployment(dictionary, out var deployment)) + applicableTo.Deployment = deployment; + + if (TryGetProjectApplicability(dictionary, out var serverless)) + applicableTo.Serverless = serverless; + + return applicableTo; + } + + private static void AssignDeploymentType(Dictionary dictionary, ApplicableTo applicableTo) + { + if (!dictionary.TryGetValue("deployment", out var deploymentType)) + return; + + if (deploymentType is null || deploymentType is string s && string.IsNullOrWhiteSpace(s)) + applicableTo.Deployment = DeploymentApplicability.All; + else if (deploymentType is string deploymentTypeString) + { + var av = ApplicabilityOverTime.TryParse(deploymentTypeString, out var a) ? a : null; + applicableTo.Deployment = new DeploymentApplicability + { + Ece = av, + Eck = av, + Ess = av, + Self = av, + }; + } + else if (deploymentType is Dictionary deploymentDictionary) + { + if (TryGetDeployment(deploymentDictionary, out var applicability)) + applicableTo.Deployment = applicability; + } + } + + private static bool TryGetDeployment(Dictionary dictionary, [NotNullWhen(true)] out DeploymentApplicability? applicability) + { + applicability = null; + var d = new DeploymentApplicability(); + var assigned = false; + if (TryGetApplicabilityOverTime(dictionary, "ece", out var ece)) + { + d.Ece = ece; + assigned = true; + } + if (TryGetApplicabilityOverTime(dictionary, "eck", out var eck)) + { + d.Eck = eck; + assigned = true; + } + + if (TryGetApplicabilityOverTime(dictionary, "ess", out var ess)) + { + d.Ess = ess; + assigned = true; + } + + if (TryGetApplicabilityOverTime(dictionary, "self", out var self)) + { + d.Self = self; + assigned = true; + } + + if (assigned) + { + applicability = d; + return true; + } + + return false; + } + + private static void AssignServerless(Dictionary dictionary, ApplicableTo applicableTo) + { + if (!dictionary.TryGetValue("serverless", out var serverless)) + return; + + if (serverless is null || serverless is string s && string.IsNullOrWhiteSpace(s)) + applicableTo.Serverless = ServerlessProjectApplicability.All; + else if (serverless is string serverlessString) + { + var av = ApplicabilityOverTime.TryParse(serverlessString, out var a) ? a : null; + applicableTo.Serverless = new ServerlessProjectApplicability + { + Elasticsearch = av, + Observability = av, + Security = av + }; + } + else if (serverless is Dictionary serverlessDictionary) + { + if (TryGetProjectApplicability(serverlessDictionary, out var applicability)) + applicableTo.Serverless = applicability; + } + } + + private static bool TryGetProjectApplicability( + Dictionary dictionary, + [NotNullWhen(true)]out ServerlessProjectApplicability? applicability + ) + { + applicability = null; + var serverlessAvailability = new ServerlessProjectApplicability(); + var assigned = false; + if (TryGetApplicabilityOverTime(dictionary, "elasticsearch", out var elasticsearch)) + { + serverlessAvailability.Elasticsearch = elasticsearch; + assigned = true; + } + if (TryGetApplicabilityOverTime(dictionary, "observability", out var observability)) + { + serverlessAvailability.Observability = observability; + assigned = true; + } + + if (TryGetApplicabilityOverTime(dictionary, "security", out var security)) + { + serverlessAvailability.Security = security; + assigned = true; + } + + if (!assigned) + return false; + applicability = serverlessAvailability; + return true; + } + + private static bool TryGetApplicabilityOverTime(Dictionary dictionary, string key, out ApplicabilityOverTime? availability) + { + availability = null; + if (!dictionary.TryGetValue(key, out var target)) + return false; + + if (target is null || target is string s && string.IsNullOrWhiteSpace(s)) + availability = ApplicabilityOverTime.GenerallyAvailable; + else if (target is string stackString) + availability = ApplicabilityOverTime.TryParse(stackString, out var a) ? a : null; + return availability is not null; + } + + public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) => + serializer.Invoke(value, type); +} diff --git a/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs b/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs index 9d4a9ff04..75b3dc53b 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs @@ -9,6 +9,7 @@ namespace Elastic.Markdown.Myst.FrontMatter; [YamlSerializable] +[Obsolete( "Use YamlFrontMatter.Apply instead see also DeploymentMode")] public record Deployment { [YamlMember(Alias = "self")] @@ -25,42 +26,46 @@ public record Deployment } [YamlSerializable] +[Obsolete( "Use YamlFrontMatter.Apply instead")] public record SelfManagedDeployment { [YamlMember(Alias = "stack")] - public ProductAvailability? Stack { get; set; } + public Applicability? Stack { get; set; } [YamlMember(Alias = "ece")] - public ProductAvailability? Ece { get; set; } + public Applicability? Ece { get; set; } [YamlMember(Alias = "eck")] - public ProductAvailability? Eck { get; set; } + public Applicability? Eck { get; set; } public static SelfManagedDeployment All { get; } = new() { - Stack = ProductAvailability.GenerallyAvailable, - Ece = ProductAvailability.GenerallyAvailable, - Eck = ProductAvailability.GenerallyAvailable + Stack = Applicability.GenerallyAvailable, + Ece = Applicability.GenerallyAvailable, + Eck = Applicability.GenerallyAvailable }; } [YamlSerializable] +[Obsolete( "Use YamlFrontMatter.Apply instead")] public record CloudManagedDeployment { [YamlMember(Alias = "hosted")] - public ProductAvailability? Hosted { get; set; } + public Applicability? Hosted { get; set; } [YamlMember(Alias = "serverless")] - public ProductAvailability? Serverless { get; set; } + public Applicability? Serverless { get; set; } public static CloudManagedDeployment All { get; } = new() { - Hosted = ProductAvailability.GenerallyAvailable, - Serverless = ProductAvailability.GenerallyAvailable + Hosted = Applicability.GenerallyAvailable, + Serverless = Applicability.GenerallyAvailable }; } +#pragma warning disable CS0618 // Type or member is obsolete +[Obsolete( "Use DeploymentAvailability instead" )] public class DeploymentConverter : IYamlTypeConverter { public bool Accepts(Type type) => type == typeof(Deployment); @@ -121,10 +126,10 @@ public class DeploymentConverter : IYamlTypeConverter } return deployment; - bool TryGetAvailability(string key, out ProductAvailability? semVersion) + bool TryGetAvailability(string key, out Applicability? semVersion) { semVersion = null; - return dictionary.TryGetValue(key, out var v) && ProductAvailability.TryParse(v, out semVersion); + return dictionary.TryGetValue(key, out var v) && Applicability.TryParse(v, out semVersion); } } @@ -132,3 +137,4 @@ bool TryGetAvailability(string key, out ProductAvailability? semVersion) public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) => serializer.Invoke(value, type); } +#pragma warning restore CS0618 // Type or member is obsolete diff --git a/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs b/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs index c8d7096f9..dce2bcae6 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs @@ -18,6 +18,10 @@ public class YamlFrontMatter [YamlMember(Alias = "sub")] public Dictionary? Properties { get; set; } - [YamlMember(Alias = "applies")] + [YamlIgnore] + [Obsolete("Use applies_to instead")] public Deployment? AppliesTo { get; set; } + + [YamlMember(Alias = "applies_to")] + public ApplicableTo? Apply { get; set; } } diff --git a/src/Elastic.Markdown/Myst/FrontMatter/ProductAvailability.cs b/src/Elastic.Markdown/Myst/FrontMatter/ProductAvailability.cs deleted file mode 100644 index c11cd1858..000000000 --- a/src/Elastic.Markdown/Myst/FrontMatter/ProductAvailability.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using Elastic.Markdown.Helpers; -using YamlDotNet.Serialization; - -namespace Elastic.Markdown.Myst.FrontMatter; - -[YamlSerializable] -public record ProductAvailability -{ - public ProductLifecycle Lifecycle { get; init; } - public SemVersion? Version { get; init; } - - public static ProductAvailability GenerallyAvailable { get; } = new() - { - Lifecycle = ProductLifecycle.GenerallyAvailable, - Version = AllVersions.Instance - }; - - // [version] - public static bool TryParse(string? value, out ProductAvailability? availability) - { - if (string.IsNullOrWhiteSpace(value) || string.Equals(value.Trim(), "all", StringComparison.InvariantCultureIgnoreCase)) - { - availability = GenerallyAvailable; - return true; - } - - var tokens = value.Split(" ", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); - if (tokens.Length < 1) - { - availability = null; - return false; - } - var lifecycle = tokens[0].ToLowerInvariant() switch - { - "preview" => ProductLifecycle.TechnicalPreview, - "tech-preview" => ProductLifecycle.TechnicalPreview, - "beta" => ProductLifecycle.Beta, - "dev" => ProductLifecycle.Development, - "development" => ProductLifecycle.Development, - "deprecated" => ProductLifecycle.Deprecated, - "coming" => ProductLifecycle.Coming, - "discontinued" => ProductLifecycle.Discontinued, - "unavailable" => ProductLifecycle.Unavailable, - "ga" => ProductLifecycle.GenerallyAvailable, - _ => throw new ArgumentOutOfRangeException(nameof(tokens), tokens, $"Unknown product lifecycle: {tokens[0]}") - }; - - var version = tokens.Length < 2 ? null : tokens[1] switch - { - null => AllVersions.Instance, - "all" => AllVersions.Instance, - "" => AllVersions.Instance, - var t => SemVersionConverter.TryParse(t, out var v) ? v : null - }; - availability = new ProductAvailability { Version = version, Lifecycle = lifecycle }; - return true; - } -} diff --git a/src/Elastic.Markdown/Myst/Settings/StructuredSettings.cs b/src/Elastic.Markdown/Myst/Settings/StructuredSettings.cs index afce6d349..c3faa0b15 100644 --- a/src/Elastic.Markdown/Myst/Settings/StructuredSettings.cs +++ b/src/Elastic.Markdown/Myst/Settings/StructuredSettings.cs @@ -37,7 +37,7 @@ public record Setting [YamlMember(Alias = "description")] public string? Description { get; set; } [YamlMember(Alias = "applies")] - public ProductAvailability? Applies { get; set; } + public Applicability? Applies { get; set; } [YamlMember(Alias = "type")] public SettingMutability Mutability { get; set; } [YamlMember(Alias = "options")] diff --git a/src/Elastic.Markdown/Myst/YamlSerialization.cs b/src/Elastic.Markdown/Myst/YamlSerialization.cs index 472407d35..06d0c47ad 100644 --- a/src/Elastic.Markdown/Myst/YamlSerialization.cs +++ b/src/Elastic.Markdown/Myst/YamlSerialization.cs @@ -17,7 +17,10 @@ public static T Deserialize(string yaml) var deserializer = new StaticDeserializerBuilder(new DocsBuilderYamlStaticContext()) .IgnoreUnmatchedProperties() .WithTypeConverter(new SemVersionConverter()) +#pragma warning disable CS0618 // Type or member is obsolete .WithTypeConverter(new DeploymentConverter()) + .WithTypeConverter(new ApplicableToConverter()) +#pragma warning restore CS0618 // Type or member is obsolete .Build(); var frontMatter = deserializer.Deserialize(input); diff --git a/src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml b/src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml new file mode 100644 index 000000000..bc59507a7 --- /dev/null +++ b/src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml @@ -0,0 +1,125 @@ +@using Elastic.Markdown.Myst.FrontMatter +@inherits RazorSlice +

+ + Applies To: + + @if (Model.Stack is not null) + { + @RenderProduct("Elastic Stack", Model.Stack) + } + + @if (Model.Deployment is not null) + { + if (Model.Deployment.Ece is not null) + { + @RenderProduct("ECE", Model.Deployment.Ece) + } + if (Model.Deployment.Eck is not null) + { + @RenderProduct("ECK", Model.Deployment.Eck) + } + if (Model.Deployment.Ess is not null) + { + @RenderProduct("Elastic Cloud", Model.Deployment.Ess) + } + if (Model.Deployment.Self is not null) + { + @RenderProduct("Self Managed", Model.Deployment.Self) + } + } + @if (Model.Serverless is not null) + { + if (Model.Serverless.AllProjects is not null) + { + @RenderProduct("Serverless", Model.Serverless.AllProjects) + } + else + { + if (Model.Serverless.Security is not null) + { + @RenderProduct("Serverless Security", Model.Serverless.Security) + } + if (Model.Serverless.Observability is not null) + { + @RenderProduct("Serverless Observability", Model.Serverless.Observability) + } + if (Model.Serverless.Security is not null) + { + @RenderProduct("Serverless Security", Model.Serverless.Security) + } + + } + + } + @if (Model.Product is not null) + { + @RenderProduct("", Model.Product) + } +

+ +@functions { + + private string GetLifeCycleClass(ProductLifecycle cycle) + { + switch (cycle) + { + case ProductLifecycle.Deprecated: + case ProductLifecycle.Coming: + case ProductLifecycle.Discontinued: + case ProductLifecycle.Unavailable: + return "muted"; + case ProductLifecycle.GenerallyAvailable: + case ProductLifecycle.TechnicalPreview: + case ProductLifecycle.Beta: + case ProductLifecycle.Development: + return "primary"; + default: + throw new ArgumentOutOfRangeException(nameof(cycle), cycle, null); + } + } + private string GetLifeCycleName(ProductLifecycle cycle) + { + switch (cycle) + { + case ProductLifecycle.TechnicalPreview: + return "Technical Preview"; + case ProductLifecycle.Beta: + return "Beta"; + case ProductLifecycle.Development: + return "Development"; + case ProductLifecycle.Deprecated: + return "Deprecated"; + case ProductLifecycle.Coming: + return "Coming"; + case ProductLifecycle.Discontinued: + return "Discontinued"; + case ProductLifecycle.Unavailable: + return "Unavailable"; + case ProductLifecycle.GenerallyAvailable: + return "GA"; + default: + throw new ArgumentOutOfRangeException(nameof(cycle), cycle, null); + } + } + + private IHtmlContent RenderProduct(string name, ApplicabilityOverTime applications) + { + foreach (var applicability in applications) + { + var c = GetLifeCycleClass(applicability.Lifecycle); + + @name + @if (applicability.Lifecycle != ProductLifecycle.GenerallyAvailable) + { + @GetLifeCycleName(applicability.Lifecycle) + } + @if (applicability.Version is not null and not AllVersions) + { + (@applicability.Version) + } + + } + return HtmlString.Empty; + } +} \ No newline at end of file diff --git a/src/Elastic.Markdown/Slices/Directives/Applies.cshtml b/src/Elastic.Markdown/Slices/Directives/Applies.cshtml deleted file mode 100644 index f34525eb8..000000000 --- a/src/Elastic.Markdown/Slices/Directives/Applies.cshtml +++ /dev/null @@ -1,96 +0,0 @@ -@using Elastic.Markdown.Myst.FrontMatter -@inherits RazorSlice -

- - Applies To: - - @if (Model.SelfManaged is not null) - { - if (Model.SelfManaged.Stack is not null) - { - @RenderProduct("Elastic Stack", Model.SelfManaged.Stack) - } - if (Model.SelfManaged.Ece is not null) - { - @RenderProduct("Elastic Cloud Enterprise", Model.SelfManaged.Ece) - } - if (Model.SelfManaged.Eck is not null) - { - @RenderProduct("Elastic Cloud Kubernetes", Model.SelfManaged.Eck) - } - } - @if (Model.Cloud is not null) - { - if (Model.Cloud.Hosted is not null) - { - @RenderProduct("Elastic Cloud Hosted", Model.Cloud.Hosted) - } - if (Model.Cloud.Serverless is not null) - { - @RenderProduct("Serverless", Model.Cloud.Serverless) - } - } -

- -@functions { - - private string GetLifeCycleClass(ProductLifecycle cycle) - { - switch (cycle) - { - case ProductLifecycle.Deprecated: - case ProductLifecycle.Coming: - case ProductLifecycle.Discontinued: - case ProductLifecycle.Unavailable: - return "muted"; - case ProductLifecycle.GenerallyAvailable: - case ProductLifecycle.TechnicalPreview: - case ProductLifecycle.Beta: - case ProductLifecycle.Development: - return "primary"; - default: - throw new ArgumentOutOfRangeException(nameof(cycle), cycle, null); - } - } - private string GetLifeCycleName(ProductLifecycle cycle) - { - switch (cycle) - { - case ProductLifecycle.TechnicalPreview: - return "Technical Preview"; - case ProductLifecycle.Beta: - return "Beta"; - case ProductLifecycle.Development: - return "Development"; - case ProductLifecycle.Deprecated: - return "Deprecated"; - case ProductLifecycle.Coming: - return "Coming"; - case ProductLifecycle.Discontinued: - return "Discontinued"; - case ProductLifecycle.Unavailable: - return "Unavailable"; - case ProductLifecycle.GenerallyAvailable: - return "GA"; - default: - throw new ArgumentOutOfRangeException(nameof(cycle), cycle, null); - } - } - - private IHtmlContent RenderProduct(string name, ProductAvailability product) - { - var c = GetLifeCycleClass(product.Lifecycle); - - @name - @if (product.Lifecycle != ProductLifecycle.GenerallyAvailable) - { - @GetLifeCycleName(product.Lifecycle) - } - @if (product.Version is not null and not AllVersions) - { - (@product.Version) - } - - return HtmlString.Empty; - } -} \ No newline at end of file diff --git a/src/Elastic.Markdown/Slices/HtmlWriter.cs b/src/Elastic.Markdown/Slices/HtmlWriter.cs index d4b10fa39..d883c46ca 100644 --- a/src/Elastic.Markdown/Slices/HtmlWriter.cs +++ b/src/Elastic.Markdown/Slices/HtmlWriter.cs @@ -68,7 +68,7 @@ public async Task RenderLayout(MarkdownFile markdown, Cancel ctx = defau NextDocument = next, NavigationHtml = navigationHtml, UrlPathPrefix = markdown.UrlPathPrefix, - Applies = markdown.YamlFrontMatter?.AppliesTo, + Applies = markdown.YamlFrontMatter?.Apply, GithubEditUrl = editUrl, AllowIndexing = DocumentationSet.Context.AllowIndexing && !markdown.Hidden }); diff --git a/src/Elastic.Markdown/Slices/Index.cshtml b/src/Elastic.Markdown/Slices/Index.cshtml index 14cd141e3..85dfdb3e9 100644 --- a/src/Elastic.Markdown/Slices/Index.cshtml +++ b/src/Elastic.Markdown/Slices/Index.cshtml @@ -21,7 +21,7 @@ @(new HtmlString(Markdown.ToHtml("# " + Model.TitleRaw))) @if (Model.Applies is not null) { - await RenderPartialAsync(Applies.Create(Model.Applies)); + await RenderPartialAsync(ApplicableTo.Create(Model.Applies)); } @(new HtmlString(Model.MarkdownHtml)) diff --git a/src/Elastic.Markdown/Slices/_ViewModels.cs b/src/Elastic.Markdown/Slices/_ViewModels.cs index 4680f926b..e50ea5651 100644 --- a/src/Elastic.Markdown/Slices/_ViewModels.cs +++ b/src/Elastic.Markdown/Slices/_ViewModels.cs @@ -20,7 +20,7 @@ public class IndexViewModel public required string NavigationHtml { get; init; } public required string? UrlPathPrefix { get; init; } public required string? GithubEditUrl { get; init; } - public required Deployment? Applies { get; init; } + public required ApplicableTo? Applies { get; init; } public required bool AllowIndexing { get; init; } } diff --git a/tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs b/tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs index e3f04105a..35fa90577 100644 --- a/tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs +++ b/tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs @@ -7,6 +7,9 @@ using FluentAssertions; using static Elastic.Markdown.Myst.FrontMatter.ProductLifecycle; +//TODO remove 'applies', Deployment and associated types when all content sets have moved over to `apply` +#pragma warning disable CS0618 // Type or member is obsolete + namespace Elastic.Markdown.Tests.FrontMatter; public class ProductConstraintTests(ITestOutputHelper output) : DirectiveTest(output, @@ -30,16 +33,16 @@ public void Assert() var appliesTo = File.YamlFrontMatter!.AppliesTo; appliesTo.Should().NotBeNull(); appliesTo!.Cloud.Should().NotBeNull(); - appliesTo.Cloud!.Serverless.Should().BeEquivalentTo(new ProductAvailability { Lifecycle = TechnicalPreview }); - appliesTo.Cloud!.Hosted.Should().BeEquivalentTo(new ProductAvailability { Lifecycle = Beta, Version = new(8, 1, 1) }); + appliesTo.Cloud!.Serverless.Should().BeEquivalentTo(new Applicability { Lifecycle = TechnicalPreview }); + appliesTo.Cloud!.Hosted.Should().BeEquivalentTo(new Applicability { Lifecycle = Beta, Version = new(8, 1, 1) }); appliesTo.SelfManaged.Should().NotBeNull(); - appliesTo.SelfManaged!.Eck.Should().BeEquivalentTo(new ProductAvailability { Lifecycle = Beta, Version = new(3, 0, 2) }); - appliesTo.SelfManaged!.Ece.Should().BeEquivalentTo(new ProductAvailability { Lifecycle = Unavailable }); - appliesTo.SelfManaged!.Stack.Should().BeEquivalentTo(new ProductAvailability { Lifecycle = GenerallyAvailable, Version = new(8, 1, 0) }); + appliesTo.SelfManaged!.Eck.Should().BeEquivalentTo(new Applicability { Lifecycle = Beta, Version = new(3, 0, 2) }); + appliesTo.SelfManaged!.Ece.Should().BeEquivalentTo(new Applicability { Lifecycle = Unavailable }); + appliesTo.SelfManaged!.Stack.Should().BeEquivalentTo(new Applicability { Lifecycle = GenerallyAvailable, Version = new(8, 1, 0) }); } } -public abstract class ParsingTests(ITestOutputHelper output, string moniker, ProductAvailability? expected) +public abstract class ParsingTests(ITestOutputHelper output, string moniker, Applicability? expected) : DirectiveTest(output, $""" --- @@ -71,8 +74,8 @@ public void Assert() public class ParsesUnavailable(ITestOutputHelper output) : ParsingTests(output, "unavailable", new() { Lifecycle = Unavailable }); public class ParsesTechnicalPreview(ITestOutputHelper output) : ParsingTests(output, "tech-preview", new() { Lifecycle = TechnicalPreview }); public class ParsesPreview(ITestOutputHelper output) : ParsingTests(output, "preview", new() { Lifecycle = TechnicalPreview }); -public class ParsesEmpty(ITestOutputHelper output) : ParsingTests(output, "", ProductAvailability.GenerallyAvailable); -public class ParsesAll(ITestOutputHelper output) : ParsingTests(output, "all", ProductAvailability.GenerallyAvailable); +public class ParsesEmpty(ITestOutputHelper output) : ParsingTests(output, "", Applicability.GenerallyAvailable); +public class ParsesAll(ITestOutputHelper output) : ParsingTests(output, "all", Applicability.GenerallyAvailable); public class ParsesWithVersion(ITestOutputHelper output) : ParsingTests(output, "ga 7.7.0", new() { Lifecycle = GenerallyAvailable, Version = new(7, 7, 0) }); public class ParsesWithAllVersion(ITestOutputHelper output) : ParsingTests(output, "ga all", new() { Lifecycle = GenerallyAvailable, Version = AllVersions.Instance }); @@ -88,7 +91,7 @@ public class CanSpecifyAllForProductVersions(ITestOutputHelper output) : Directi { [Fact] public void Assert() => - File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should().BeEquivalentTo(ProductAvailability.GenerallyAvailable); + File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should().BeEquivalentTo(Applicability.GenerallyAvailable); } public class EmptyProductVersionMeansAll(ITestOutputHelper output) : DirectiveTest(output, @@ -103,7 +106,7 @@ public class EmptyProductVersionMeansAll(ITestOutputHelper output) : DirectiveTe { [Fact] public void Assert() => - File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should().BeEquivalentTo(ProductAvailability.GenerallyAvailable); + File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should().BeEquivalentTo(Applicability.GenerallyAvailable); } public class EmptyCloudSetsAllCloudProductsToAll(ITestOutputHelper output) : DirectiveTest(output, @@ -118,7 +121,7 @@ public class EmptyCloudSetsAllCloudProductsToAll(ITestOutputHelper output) : Dir { [Fact] public void Assert() => - File.YamlFrontMatter!.AppliesTo!.Cloud!.Hosted.Should().BeEquivalentTo(ProductAvailability.GenerallyAvailable); + File.YamlFrontMatter!.AppliesTo!.Cloud!.Hosted.Should().BeEquivalentTo(Applicability.GenerallyAvailable); } public class EmptySelfSetsAllSelfManagedProductsToAll(ITestOutputHelper output) : DirectiveTest(output, @@ -136,9 +139,9 @@ public class EmptySelfSetsAllSelfManagedProductsToAll(ITestOutputHelper output) public void Assert() { File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Eck.Should() - .BeEquivalentTo(ProductAvailability.GenerallyAvailable); + .BeEquivalentTo(Applicability.GenerallyAvailable); File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should() - .BeEquivalentTo(new ProductAvailability { Lifecycle = Deprecated, Version = new(9, 0, 0) }); + .BeEquivalentTo(new Applicability { Lifecycle = Deprecated, Version = new(9, 0, 0) }); } } @@ -154,6 +157,6 @@ public class CloudProductsOverwriteDeploymentType(ITestOutputHelper output) : Di { [Fact] public void Assert() => - File.YamlFrontMatter!.AppliesTo!.Cloud!.Hosted.Should().BeEquivalentTo(ProductAvailability.GenerallyAvailable); + File.YamlFrontMatter!.AppliesTo!.Cloud!.Hosted.Should().BeEquivalentTo(Applicability.GenerallyAvailable); } diff --git a/tests/authoring/Availability/ApplyYaml.fs b/tests/authoring/Availability/ApplyYaml.fs new file mode 100644 index 000000000..e12e9a947 --- /dev/null +++ b/tests/authoring/Availability/ApplyYaml.fs @@ -0,0 +1,179 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +module ``product availability``.``yaml frontmatter`` + +open System.Collections +open Elastic.Markdown.Helpers +open Elastic.Markdown.Myst.FrontMatter +open JetBrains.Annotations +open Xunit +open authoring +open authoring.MarkdownDocumentAssertions + +let frontMatter ([]m: string) = + Setup.Document $"""--- +{m} +--- +# Document +""" + +type ``apply defaults to all`` () = + static let markdown = frontMatter """ +applies_to: +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo ApplicableTo.All + +type ``apply default to top level arguments`` () = + static let markdown = frontMatter """ +applies_to: + deployment: + serverless: +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo (ApplicableTo( + Deployment=DeploymentApplicability.All, + Serverless=ServerlessProjectApplicability.All + )) + +type ``parses serverless as string to set all projects`` () = + static let markdown = frontMatter """ +applies_to: + serverless: ga 9.0.0 +""" + [] + let ``apply matches expected`` () = + let expectedAvailability = ApplicabilityOverTime.op_Explicit "ga 9.0.0" + markdown |> appliesTo (ApplicableTo( + Serverless=ServerlessProjectApplicability( + Elasticsearch=expectedAvailability, + Observability=expectedAvailability, + Security=expectedAvailability + ) + )) + +type ``parses serverless projects`` () = + static let markdown = frontMatter """ +applies_to: + serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo (ApplicableTo( + Serverless=ServerlessProjectApplicability( + Security=ApplicabilityOverTime.op_Explicit "ga 9.0.0", + Elasticsearch=ApplicabilityOverTime.op_Explicit "beta 9.1.0", + Observability=ApplicabilityOverTime.op_Explicit "discontinued 9.2.0" + ) + )) + +type ``parses stack`` () = + static let markdown = frontMatter """ +applies_to: + stack: ga 9.1 +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo (ApplicableTo( + Stack=ApplicabilityOverTime.op_Explicit "ga 9.1.0" + )) + +type ``parses deployment as string to set all deployment targets`` () = + static let markdown = frontMatter """ +applies_to: + deployment: ga 9.0.0 +""" + [] + let ``apply matches expected`` () = + let expectedAvailability = ApplicabilityOverTime.op_Explicit "ga 9.0.0" + markdown |> appliesTo (ApplicableTo( + Deployment=DeploymentApplicability( + Eck=expectedAvailability, + Ess=expectedAvailability, + Ece=expectedAvailability, + Self=expectedAvailability + ) + )) + +type ``parses deployment types as individual properties`` () = + static let markdown = frontMatter """ +applies_to: + deployment: + eck: ga 9.0 + ess: beta 9.1 + ece: discontinued 9.2.0 + self: unavailable 9.3.0 +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo (ApplicableTo( + Deployment=DeploymentApplicability( + Eck=ApplicabilityOverTime.op_Explicit "ga 9.0", + Ess=ApplicabilityOverTime.op_Explicit "beta 9.1", + Ece=ApplicabilityOverTime.op_Explicit "discontinued 9.2.0", + Self=ApplicabilityOverTime.op_Explicit "unavailable 9.3.0" + ) + )) + +type ``parses product`` () = + static let markdown = frontMatter """ +applies_to: + product: coming 9.5 +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo (ApplicableTo( + Product=ApplicabilityOverTime.op_Explicit "coming 9.5.0" + )) + +type ``parses product multiple`` () = + static let markdown = frontMatter """ +applies_to: + product: coming 9.5, discontinued 9.7 +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo (ApplicableTo( + Product=ApplicabilityOverTime([ + Applicability.op_Explicit "coming 9.5"; + Applicability.op_Explicit "discontinued 9.7" + ] |> Array.ofList) + )) + +type ``lenient to defining types at top level`` () = + static let markdown = frontMatter """ +applies_to: + eck: ga 9.0 + ess: beta 9.1 + ece: discontinued 9.2.0 + self: unavailable 9.3.0 + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 + product: coming 9.5, discontinued 9.7 + stack: ga 9.1 +""" + [] + let ``apply matches expected`` () = + markdown |> appliesTo (ApplicableTo( + Deployment=DeploymentApplicability( + Eck=ApplicabilityOverTime.op_Explicit "ga 9.0", + Ess=ApplicabilityOverTime.op_Explicit "beta 9.1", + Ece=ApplicabilityOverTime.op_Explicit "discontinued 9.2.0", + Self=ApplicabilityOverTime.op_Explicit "unavailable 9.3.0" + ), + Serverless=ServerlessProjectApplicability( + Security=ApplicabilityOverTime.op_Explicit "ga 9.0.0", + Elasticsearch=ApplicabilityOverTime.op_Explicit "beta 9.1.0", + Observability=ApplicabilityOverTime.op_Explicit "discontinued 9.2.0" + ), + Stack=ApplicabilityOverTime.op_Explicit "ga 9.1.0", + Product=ApplicabilityOverTime.op_Explicit "coming 9.5, discontinued 9.7" + )) diff --git a/tests/authoring/Framework/MarkdownDocumentAssertions.fs b/tests/authoring/Framework/MarkdownDocumentAssertions.fs index c5d3c3a77..23dc9d8d4 100644 --- a/tests/authoring/Framework/MarkdownDocumentAssertions.fs +++ b/tests/authoring/Framework/MarkdownDocumentAssertions.fs @@ -5,7 +5,9 @@ namespace authoring open System.Diagnostics +open Elastic.Markdown.Myst.FrontMatter open Markdig.Syntax +open Swensen.Unquote open Xunit.Sdk module MarkdownDocumentAssertions = @@ -22,4 +24,17 @@ module MarkdownDocumentAssertions = let unsupportedBlocks = actual.MinimalParse.Descendants<'element>() |> Array.ofSeq if unsupportedBlocks.Length = 0 then raise (XunitException($"Could not find {typedefof<'element>.Name} in minimally parsed document")) - unsupportedBlocks; + unsupportedBlocks + + [] + let appliesTo (expectedAvailability: ApplicableTo) (actual: Lazy) = + let actual = actual.Value + let result = actual.MarkdownResults |> Seq.head + let matter = result.File.YamlFrontMatter + match matter with + | NonNull m -> + let apply = m.Apply + test <@ apply = expectedAvailability @> + | _ -> failwithf "%s has no yamlfront matter" result.File.RelativePath + + diff --git a/tests/authoring/authoring.fsproj b/tests/authoring/authoring.fsproj index 6e05e70db..e9d0bf910 100644 --- a/tests/authoring/authoring.fsproj +++ b/tests/authoring/authoring.fsproj @@ -60,4 +60,8 @@ + + + + From 1ae90f5def772577f45960ae7dda4e312b864bb2 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Tue, 18 Feb 2025 12:36:19 +0100 Subject: [PATCH 2/7] Add directive block parsing for applies_to --- docs/syntax/applies.md | 135 ++++++++++++++---- docs/syntax/img/applies.png | Bin 0 -> 251694 bytes docs/syntax/index.md | 9 ++ .../Myst/CodeBlocks/EnhancedCodeBlock.cs | 7 + .../EnhancedCodeBlockHtmlRenderer.cs | 16 +++ .../CodeBlocks/EnhancedCodeBlockParser.cs | 33 ++++- .../Myst/Directives/DirectiveBlockParser.cs | 9 +- .../Applicability/AppliesToDirective.fs | 58 ++++++++ .../AppliesToFrontMatter.fs} | 2 - .../authoring/Blocks/CodeBlocks/CodeBlocks.fs | 10 +- .../Framework/MarkdownDocumentAssertions.fs | 10 ++ tests/authoring/authoring.fsproj | 3 +- 12 files changed, 254 insertions(+), 38 deletions(-) create mode 100644 docs/syntax/img/applies.png create mode 100644 tests/authoring/Applicability/AppliesToDirective.fs rename tests/authoring/{Availability/ApplyYaml.fs => Applicability/AppliesToFrontMatter.fs} (99%) diff --git a/docs/syntax/applies.md b/docs/syntax/applies.md index 4208c2c16..b6f2cf90a 100644 --- a/docs/syntax/applies.md +++ b/docs/syntax/applies.md @@ -15,38 +15,42 @@ applies_to: # Applies to +Allows you to annotate a page or section's applicability. -Using yaml frontmatter pages can explicitly indicate to each deployment targets availability and lifecycle status - +### Syntax -```yaml -applies_to: - stack: ga 9.1 - deployment: - eck: ga 9.0 - ess: beta 9.1 - ece: discontinued 9.2.0 - self: unavailable 9.3.0 - serverless: - security: ga 9.0.0 - elasticsearch: beta 9.1.0 - observability: discontinued 9.2.0 - product: coming 9.5, discontinued 9.7 +``` + [version], [version] ``` -Its syntax is +Taking a mandatory [life-cycle](#life-cycle) with an optional version. + +#### Life cycle: + * `preview` + * `beta` + * `development` + * `deprecated` + * `coming` + * `discontinued` + * `unavailable` + * `ga` + +#### Version + +Can be in either `major.minor` or `major.minor.patch` format + +#### Examples ``` - : [version] +coming 9.5, discontinued 9.7 +discontinued 9.2.0 +all ``` -Where version is optional. - `all` and empty string mean generally available for all active versions ```yaml applies: - stack: serverless: all ``` @@ -58,19 +62,94 @@ applies: serverless: beta ``` -Are equivalent, note `all` just means we won't be rendering the version portion in the html. +Both are equivalent, note `all` just means we won't be rendering the version portion in the html. -## This section has its own applies annotations [#sections] +## Structured model -:::{applies} -:serverless: unavailable -::: +![Applies To Model](img/applies.png) + +The above model is projected to the following structured yaml. + +```yaml +--- +applies_to: + stack: + deployment: + eck: + ess: + ece: + self: + serverless: + security: + elasticsearch: + observability: + product: +--- +``` +This allows you to annotate various facets as defined in [](../migration/versioning.md) + +## Page annotations + +Using yaml frontmatter pages can explicitly indicate to each deployment targets availability and lifecycle status + + +```yaml +--- +applies_to: + stack: ga 9.1 + deployment: + eck: ga 9.0 + ess: beta 9.1 + ece: discontinued 9.2.0 + self: unavailable 9.3.0 + serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 + product: coming 9.5, discontinued 9.7 +--- +``` + + +## Section annotation [#sections] + +```yaml {applies_to} +stack: ga 9.1 +deployment: + eck: ga 9.0 + ess: beta 9.1 + ece: discontinued 9.2.0 + self: unavailable 9.3.0 +serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 +product: coming 9.5, discontinued 9.7 +``` + +A header may be followed by an `{applies_to}` directive which will contextualize the applicability +of the section further. :::{note} -the `{applies}` directive **MUST** be preceded by a heading. +the `{applies_to}` directive **MUST** be preceded by a heading directly. ::: -This section describes a feature that's unavailable in `stack` and `ga` in all cloud products -however its tech preview on `serverless` since it overrides what `cloud` specified. +Note that this directive needs triple backticks since its content is literal. See also [](index.md#literal-directives) + +````markdown +```{applies_to} +stack: ga 9.1 +``` +```` + +In order to play even better with markdown editors the following is also supported: + +````markdown +```yaml {applies_to} +stack: ga 9.1 +``` +```` + +This will allow the yaml inside the `{applies-to}` directive to be fully highlighted. diff --git a/docs/syntax/img/applies.png b/docs/syntax/img/applies.png new file mode 100644 index 0000000000000000000000000000000000000000..170d00ba6973920285c6ab67073e449f6cd07fa2 GIT binary patch literal 251694 zcmeFZ2UJtb+As{FqM)Dxf^-`oEg&GBpr|Mv0Rbsd5b3>ynt&cfx{4HOL69O#?j&b{~C`>pp~tiO2wb+T5HJ$uhQGf$nTOcJK2qkfculYxeY z=IG5ES8vhK91)_Sp&LDP5V#}H>?jA^(6U!k)4Qpr#;@n$`oP}FhKA-wSe!AviGeYf z3iSS!L&u&5N4`toKXW!X^4RSmuFHm3PVh%^usjUsx^VlQ%khu;y~1klMylbAY;RYO|!_6MaLelVH^6aK`@b$Z-4lj2QAGF>E`(>)%?s; ze6%0T4%{+Tp}BhDTc<5XGtQT%S>YlFf3u86%G<_5jg+EBcKV*{0ReZd7?v+WmY zd*&V~<*PnB>^&!8_VwKH@bkxrmzQD_WYrF>oq6h<&YTik)Nh*u&x*y%c5WWmRsnnN z&-XYb?GbDu-ihhPgWK1TVjyElrBE5C1=G@JCN^E~Tw**P{C1&4q1pBP{B!+dj O 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 z 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 =FchlA#9x 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⫬el14_)&=N#bwCBTo;pV*Very=7FC{ogN2cQb%U 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 literal 0 HcmV?d00001 diff --git a/docs/syntax/index.md b/docs/syntax/index.md index e481c8735..32acb8d79 100644 --- a/docs/syntax/index.md +++ b/docs/syntax/index.md @@ -29,6 +29,8 @@ Nested content that will be parsed as markdown Defining directives with `:::` allows the nested markdown syntax to be highlighted properly by editors and web viewers. + + ### Nesting Directives Increase the number of leading semicolons to include nested directives. @@ -46,6 +48,13 @@ Content displayed in the note admonition ## Literal directives +All directive are indicated with semicolons except literal blocks. For these you need to use triple backticks. + +* [Code blocks](code.md) +* [{applies-to} blocks](applies.md) + +Since their contents **should not** be parsed as markdown they use backticks. This also ensures maximum interopability with existing markdown editors and previews. + Many Markdown editors support syntax highlighting for embedded code blocks. For compatibility with this feature, use triple backticks instead of triple colons for content that needs to be displayed literally: ````markdown diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs index b15a4b3cc..4433efaee 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs @@ -4,11 +4,18 @@ using System.IO.Abstractions; using Elastic.Markdown.Myst.Directives; +using Elastic.Markdown.Myst.FrontMatter; using Markdig.Parsers; using Markdig.Syntax; namespace Elastic.Markdown.Myst.CodeBlocks; +public class AppliesToDirective(BlockParser parser, ParserContext context) + : EnhancedCodeBlock(parser, context) +{ + public ApplicableTo? AppliesTo { get; set; } +} + public class EnhancedCodeBlock(BlockParser parser, ParserContext context) : FencedCodeBlock(parser), IBlockExtension { diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs index 04315ebbc..940081aa1 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs @@ -108,6 +108,12 @@ private static int CountIndentation(StringSlice slice) protected override void Write(HtmlRenderer renderer, EnhancedCodeBlock block) { + if (block is AppliesToDirective appliesToDirective) + { + RenderAppliesToHtml(renderer, appliesToDirective); + return; + } + var callOuts = block.UniqueCallOuts; var slice = Code.Create(new CodeViewModel @@ -184,4 +190,14 @@ protected override void Write(HtmlRenderer renderer, EnhancedCodeBlock block) renderer.WriteLine(""); } } + + private static void RenderAppliesToHtml(HtmlRenderer renderer, AppliesToDirective appliesToDirective) + { + var appliesTo = appliesToDirective.AppliesTo; + var slice2 = ApplicableTo.Create(appliesTo); + if (appliesTo is null || appliesTo == FrontMatter.ApplicableTo.All) + return; + var html = slice2.RenderAsync().GetAwaiter().GetResult(); + renderer.Write(html); + } } diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs index 5cd0787c8..b70c39fcd 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs @@ -5,6 +5,7 @@ using System.Text.RegularExpressions; using Elastic.Markdown.Diagnostics; using Elastic.Markdown.Helpers; +using Elastic.Markdown.Myst.FrontMatter; using Markdig.Helpers; using Markdig.Parsers; using Markdig.Syntax; @@ -30,7 +31,10 @@ protected override EnhancedCodeBlock CreateFencedBlock(BlockProcessor processor) if (processor.Context is not ParserContext context) throw new Exception("Expected parser context to be of type ParserContext"); - var codeBlock = new EnhancedCodeBlock(this, context) { IndentCount = processor.Indent }; + var lineSpan = processor.Line.AsSpan(); + var codeBlock = lineSpan.IndexOf("{applies_to}") > -1 + ? new AppliesToDirective(this, context) { IndentCount = processor.Indent } + : new EnhancedCodeBlock(this, context) { IndentCount = processor.Indent }; if (processor.TrackTrivia) { @@ -91,8 +95,30 @@ public override bool Close(BlockProcessor processor, Block block) codeBlock.EmitWarning($"Unknown language: {codeBlock.Language}"); var lines = codeBlock.Lines; - var callOutIndex = 0; + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + if (lines.Lines is null) + return base.Close(processor, block); + + if (codeBlock is not AppliesToDirective appliesToDirective) + ProcessCallOuts(lines, language, codeBlock, context); + else + ProcessAppliesToDirective(appliesToDirective, lines, context); + + return base.Close(processor, block); + } + + private static void ProcessAppliesToDirective(AppliesToDirective appliesToDirective, StringLineGroup lines, ParserContext context) + { + var yaml = lines.ToSlice().AsSpan().ToString(); + var applicableTo = YamlSerialization.Deserialize(yaml); + appliesToDirective.AppliesTo = applicableTo; + } + + private static void ProcessCallOuts(StringLineGroup lines, string language, EnhancedCodeBlock codeBlock, + ParserContext context) + { + var callOutIndex = 0; var originatingLine = 0; for (var index = 0; index < lines.Lines.Length; index++) { @@ -141,7 +167,6 @@ public override bool Close(BlockProcessor processor, Block block) //update string slices to ignore call outs if (codeBlock.CallOuts.Count > 0) { - var callouts = codeBlock.CallOuts.Aggregate(new Dictionary(), (acc, curr) => { if (acc.TryAdd(curr.Line, curr)) @@ -168,8 +193,6 @@ public override bool Close(BlockProcessor processor, Block block) if (inlineAnnotations > 0) codeBlock.InlineAnnotations = true; - - return base.Close(processor, block); } private static List EnumerateAnnotations(Regex.ValueMatchEnumerator matches, diff --git a/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs b/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs index 22ad8b4ec..eb2108de1 100644 --- a/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs +++ b/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs @@ -153,12 +153,19 @@ public override BlockState TryOpen(BlockProcessor processor) return BlockState.None; } - if (line.IndexOf("{") == -1) + if (line.IndexOf("{") <= -1) return BlockState.None; if (line.IndexOf("}") == -1) return BlockState.None; + var span = line.AsSpan(); + var lastIndent = span.LastIndexOf(":"); + var startApplies = span.IndexOf("{applies_to}"); + var startOpen = span.IndexOf("{"); + if (startOpen > lastIndent + 1 || startApplies != -1) + return BlockState.None; + return base.TryOpen(processor); } diff --git a/tests/authoring/Applicability/AppliesToDirective.fs b/tests/authoring/Applicability/AppliesToDirective.fs new file mode 100644 index 000000000..fb3148618 --- /dev/null +++ b/tests/authoring/Applicability/AppliesToDirective.fs @@ -0,0 +1,58 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +module ``product availability``.``yaml directive`` + +open Elastic.Markdown.Myst.FrontMatter +open authoring +open authoring.MarkdownDocumentAssertions +open Swensen.Unquote +open Xunit +open Elastic.Markdown.Myst.CodeBlocks + +type ``piggy back off yaml formatting`` () = + static let markdown = Setup.Markdown """ +```yaml {applies_to} +serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 +``` +""" + + [] + let ``parses to AppliesDirective`` () = + let directives = markdown |> converts "index.md" |> parses + test <@ directives.Length = 1 @> + + directives |> appliesToDirective (ApplicableTo( + Serverless=ServerlessProjectApplicability( + Security=ApplicabilityOverTime.op_Explicit "ga 9.0.0", + Elasticsearch=ApplicabilityOverTime.op_Explicit "beta 9.1.0", + Observability=ApplicabilityOverTime.op_Explicit "discontinued 9.2.0" + ) + )) + +type ``plain block`` () = + static let markdown = Setup.Markdown """ +```{applies_to} +serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 +``` +""" + + [] + let ``parses to AppliesDirective`` () = + let directives = markdown |> converts "index.md" |> parses + test <@ directives.Length = 1 @> + + directives |> appliesToDirective (ApplicableTo( + Serverless=ServerlessProjectApplicability( + Security=ApplicabilityOverTime.op_Explicit "ga 9.0.0", + Elasticsearch=ApplicabilityOverTime.op_Explicit "beta 9.1.0", + Observability=ApplicabilityOverTime.op_Explicit "discontinued 9.2.0" + ) + )) \ No newline at end of file diff --git a/tests/authoring/Availability/ApplyYaml.fs b/tests/authoring/Applicability/AppliesToFrontMatter.fs similarity index 99% rename from tests/authoring/Availability/ApplyYaml.fs rename to tests/authoring/Applicability/AppliesToFrontMatter.fs index e12e9a947..87fcb5426 100644 --- a/tests/authoring/Availability/ApplyYaml.fs +++ b/tests/authoring/Applicability/AppliesToFrontMatter.fs @@ -4,8 +4,6 @@ module ``product availability``.``yaml frontmatter`` -open System.Collections -open Elastic.Markdown.Helpers open Elastic.Markdown.Myst.FrontMatter open JetBrains.Annotations open Xunit diff --git a/tests/authoring/Blocks/CodeBlocks/CodeBlocks.fs b/tests/authoring/Blocks/CodeBlocks/CodeBlocks.fs index fb01f5f0e..287bdee02 100644 --- a/tests/authoring/Blocks/CodeBlocks/CodeBlocks.fs +++ b/tests/authoring/Blocks/CodeBlocks/CodeBlocks.fs @@ -4,8 +4,11 @@ module ``block elements``.``code blocks`` +open Elastic.Markdown.Myst.CodeBlocks +open Swensen.Unquote open Xunit open authoring +open authoring.MarkdownDocumentAssertions type ``warns on invalid language`` () = static let markdown = Setup.Markdown """ @@ -15,4 +18,9 @@ type ``warns on invalid language`` () = [] let ``validate HTML: generates link and alt attr`` () = - markdown |> hasWarning "Unknown language: not-a-valid-language" \ No newline at end of file + markdown |> hasWarning "Unknown language: not-a-valid-language" + + [] + let ``parses to EnhancedCodeBlock`` () = + let codeBlocks = markdown |> converts "index.md" |> parses + test <@ codeBlocks.Length = 1 @> diff --git a/tests/authoring/Framework/MarkdownDocumentAssertions.fs b/tests/authoring/Framework/MarkdownDocumentAssertions.fs index 23dc9d8d4..d52bc5216 100644 --- a/tests/authoring/Framework/MarkdownDocumentAssertions.fs +++ b/tests/authoring/Framework/MarkdownDocumentAssertions.fs @@ -5,6 +5,7 @@ namespace authoring open System.Diagnostics +open Elastic.Markdown.Myst.CodeBlocks open Elastic.Markdown.Myst.FrontMatter open Markdig.Syntax open Swensen.Unquote @@ -38,3 +39,12 @@ module MarkdownDocumentAssertions = | _ -> failwithf "%s has no yamlfront matter" result.File.RelativePath + [] + let appliesToDirective (expectedAvailability: ApplicableTo) (actual: AppliesToDirective array) = + let actual = actual |> Array.tryHead + match actual with + | Some d -> + let apply = d.AppliesTo + test <@ apply = expectedAvailability @> + | _ -> failwithf "Could not locate an AppliesToDirective" + diff --git a/tests/authoring/authoring.fsproj b/tests/authoring/authoring.fsproj index e9d0bf910..6104b5531 100644 --- a/tests/authoring/authoring.fsproj +++ b/tests/authoring/authoring.fsproj @@ -61,7 +61,8 @@ - + + From 54c0f65011d797a8a6ab2bf221ef437f89d6fb7a Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Tue, 18 Feb 2025 14:04:00 +0100 Subject: [PATCH 3/7] update styling --- docs/syntax/applies.md | 40 +++++++++++++++++++ src/Elastic.Markdown/Assets/styles.css | 24 +++++++++++ .../CodeBlocks/EnhancedCodeBlockParser.cs | 12 +++++- .../Slices/Directives/ApplicableTo.cshtml | 13 +++--- 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/docs/syntax/applies.md b/docs/syntax/applies.md index b6f2cf90a..f82cb519b 100644 --- a/docs/syntax/applies.md +++ b/docs/syntax/applies.md @@ -153,3 +153,43 @@ stack: ga 9.1 ```` This will allow the yaml inside the `{applies-to}` directive to be fully highlighted. + + +## Examples + +#### Stack only +```yaml {applies_to} +stack: ga 9.1 +``` + +#### Stack with deployment +```yaml {applies_to} +stack: ga 9.1 +deployment: + eck: ga 9.0 + ess: beta 9.1 +``` + +#### Deployment only +```yaml {applies_to} +deployment: + ece: discontinued 9.2.0 + self: unavailable 9.3.0 +``` + +#### Serverless only +```yaml {applies_to} +serverless: ga 9.0.0 +``` + +#### Serverless with project differences +```yaml {applies_to} +serverless: + security: ga 9.0.0 + elasticsearch: beta 9.1.0 + observability: discontinued 9.2.0 +``` +#### Stack with product +```yaml {applies_to} +stack: ga 9.1 +``` diff --git a/src/Elastic.Markdown/Assets/styles.css b/src/Elastic.Markdown/Assets/styles.css index 7c237e978..7867452b5 100644 --- a/src/Elastic.Markdown/Assets/styles.css +++ b/src/Elastic.Markdown/Assets/styles.css @@ -87,6 +87,30 @@ .content-container { @apply w-full max-w-[80ch]; } + + .applies { + border-bottom: 1px solid var(--color-gray-300); + padding-bottom: calc(var(--spacing) * 3); + font-family: "Mier B", "Inter", sans-serif; + + .applies-to-label { + display: block; + font-size: 1.5em; + font-weight: var(--font-weight-extrabold); + padding-bottom: calc(var(--spacing) * 3); + } + .applicable-info { + padding: calc(var(--spacing) * 0.5); + padding-left: calc(var(--spacing) * 2); + padding-right: calc(var(--spacing) * 2); + margin: calc(var(--spacing) * 0.5); + display: inline-block; + font-size: 0.8em; + border-radius: 0.4em; + background-color: var(--color-white); + border: 1px solid var(--color-gray-300); + } + } } * { diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs index b70c39fcd..5b0957c71 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs @@ -111,8 +111,16 @@ private static void ProcessAppliesToDirective(AppliesToDirective appliesToDirect { var yaml = lines.ToSlice().AsSpan().ToString(); - var applicableTo = YamlSerialization.Deserialize(yaml); - appliesToDirective.AppliesTo = applicableTo; + try + { + var applicableTo = YamlSerialization.Deserialize(yaml); + appliesToDirective.AppliesTo = applicableTo; + + } + catch (Exception e) + { + appliesToDirective.EmitError($"Unable to parse applies_to directive: {yaml}", e); + } } private static void ProcessCallOuts(StringLineGroup lines, string language, EnhancedCodeBlock codeBlock, diff --git a/src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml b/src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml index bc59507a7..fc0950d3c 100644 --- a/src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml +++ b/src/Elastic.Markdown/Slices/Directives/ApplicableTo.cshtml @@ -1,14 +1,11 @@ @using Elastic.Markdown.Myst.FrontMatter @inherits RazorSlice -

- - Applies To: - +

+ @if (Model.Stack is not null) { @RenderProduct("Elastic Stack", Model.Stack) } - @if (Model.Deployment is not null) { if (Model.Deployment.Ece is not null) @@ -108,15 +105,15 @@ foreach (var applicability in applications) { var c = GetLifeCycleClass(applicability.Lifecycle); - + @name @if (applicability.Lifecycle != ProductLifecycle.GenerallyAvailable) { - @GetLifeCycleName(applicability.Lifecycle) + @GetLifeCycleName(applicability.Lifecycle) } @if (applicability.Version is not null and not AllVersions) { - (@applicability.Version) + (@applicability.Version) } } From b41fa67eed70ace440789a98fa753e6132a41455 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Tue, 18 Feb 2025 14:09:12 +0100 Subject: [PATCH 4/7] cleanup and fix tests --- .../Myst/Directives/DirectiveBlockParser.cs | 2 +- .../Myst/FrontMatter/FrontMatterParser.cs | 6 +- src/Elastic.Markdown/Slices/HtmlWriter.cs | 2 +- .../Directives/AppliesBlockTests.cs | 80 --------- .../FrontMatter/ProductConstraintTests.cs | 162 ------------------ .../Framework/MarkdownDocumentAssertions.fs | 2 +- 6 files changed, 4 insertions(+), 250 deletions(-) delete mode 100644 tests/Elastic.Markdown.Tests/Directives/AppliesBlockTests.cs delete mode 100644 tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs diff --git a/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs b/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs index eb2108de1..0682980b6 100644 --- a/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs +++ b/src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs @@ -160,7 +160,7 @@ public override BlockState TryOpen(BlockProcessor processor) return BlockState.None; var span = line.AsSpan(); - var lastIndent = span.LastIndexOf(":"); + var lastIndent = Math.Max(span.LastIndexOf("`"), span.LastIndexOf(":")); var startApplies = span.IndexOf("{applies_to}"); var startOpen = span.IndexOf("{"); if (startOpen > lastIndent + 1 || startApplies != -1) diff --git a/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs b/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs index dce2bcae6..8a88772e2 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs @@ -18,10 +18,6 @@ public class YamlFrontMatter [YamlMember(Alias = "sub")] public Dictionary? Properties { get; set; } - [YamlIgnore] - [Obsolete("Use applies_to instead")] - public Deployment? AppliesTo { get; set; } - [YamlMember(Alias = "applies_to")] - public ApplicableTo? Apply { get; set; } + public ApplicableTo? AppliesTo { get; set; } } diff --git a/src/Elastic.Markdown/Slices/HtmlWriter.cs b/src/Elastic.Markdown/Slices/HtmlWriter.cs index d883c46ca..d4b10fa39 100644 --- a/src/Elastic.Markdown/Slices/HtmlWriter.cs +++ b/src/Elastic.Markdown/Slices/HtmlWriter.cs @@ -68,7 +68,7 @@ public async Task RenderLayout(MarkdownFile markdown, Cancel ctx = defau NextDocument = next, NavigationHtml = navigationHtml, UrlPathPrefix = markdown.UrlPathPrefix, - Applies = markdown.YamlFrontMatter?.Apply, + Applies = markdown.YamlFrontMatter?.AppliesTo, GithubEditUrl = editUrl, AllowIndexing = DocumentationSet.Context.AllowIndexing && !markdown.Hidden }); diff --git a/tests/Elastic.Markdown.Tests/Directives/AppliesBlockTests.cs b/tests/Elastic.Markdown.Tests/Directives/AppliesBlockTests.cs deleted file mode 100644 index b24729d45..000000000 --- a/tests/Elastic.Markdown.Tests/Directives/AppliesBlockTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using Elastic.Markdown.Diagnostics; -using Elastic.Markdown.Myst.Directives; -using FluentAssertions; - -namespace Elastic.Markdown.Tests.Directives; - -public class AppliesBlockTests(ITestOutputHelper output) : DirectiveTest(output, -""" -# heading -:::{applies} -:eck: unavailable -::: -""" -) -{ - [Fact] - public void ParsesBlock() => Block.Should().NotBeNull(); - - [Fact] - public void IncludesProductAvailability() => - Html.Should().Contain("Unavailable") - .And.Contain("Elastic Cloud Kubernetes") - .And.Contain("Applies To:"); - - - [Fact] - public void NoErrors() => Collector.Diagnostics.Should().BeEmpty(); -} - -public class EmptyAppliesBlock(ITestOutputHelper output) : DirectiveTest(output, -""" - -A paragraph that's not a heading - -```{applies} -``` -""" -) -{ - [Fact] - public void ParsesBlock() => Block.Should().NotBeNull(); - - [Fact] - public void DoesNotRender() => - Html.Should().Be("

A paragraph that's not a heading

"); - - [Fact] - public void EmitErrorOnEmptyBlock() - { - Collector.Diagnostics.Should().NotBeNullOrEmpty().And.HaveCount(2); - Collector.Diagnostics.Should().OnlyContain(d => d.Severity == Severity.Error); - Collector.Diagnostics.Should() - .Contain(d => d.Message.Contains("{applies} block with no product availability specified")); - - Collector.Diagnostics.Should() - .Contain(d => d.Message.Contains("{applies} should follow a heading")); - } -} - -// ensures we allow for empty lines between heading and applies block -public class AppliesHeadingTests(ITestOutputHelper output) : DirectiveTest(output, -""" -# heading - - - -```{applies} -:eck: unavailable -``` -""" -) -{ - [Fact] - public void NoErrors() => Collector.Diagnostics.Should().BeEmpty(); -} - diff --git a/tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs b/tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs deleted file mode 100644 index 35fa90577..000000000 --- a/tests/Elastic.Markdown.Tests/FrontMatter/ProductConstraintTests.cs +++ /dev/null @@ -1,162 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using Elastic.Markdown.Myst.FrontMatter; -using Elastic.Markdown.Tests.Directives; -using FluentAssertions; -using static Elastic.Markdown.Myst.FrontMatter.ProductLifecycle; - -//TODO remove 'applies', Deployment and associated types when all content sets have moved over to `apply` -#pragma warning disable CS0618 // Type or member is obsolete - -namespace Elastic.Markdown.Tests.FrontMatter; - -public class ProductConstraintTests(ITestOutputHelper output) : DirectiveTest(output, -""" ---- -navigation_title: "Documentation Guide" -applies: - stack: ga 8.1 - serverless: tech-preview - hosted: beta 8.1.1 - eck: beta 3.0.2 - ece: unavailable ---- -""" -) -{ - [Fact] - public void Assert() - { - File.YamlFrontMatter.Should().NotBeNull(); - var appliesTo = File.YamlFrontMatter!.AppliesTo; - appliesTo.Should().NotBeNull(); - appliesTo!.Cloud.Should().NotBeNull(); - appliesTo.Cloud!.Serverless.Should().BeEquivalentTo(new Applicability { Lifecycle = TechnicalPreview }); - appliesTo.Cloud!.Hosted.Should().BeEquivalentTo(new Applicability { Lifecycle = Beta, Version = new(8, 1, 1) }); - appliesTo.SelfManaged.Should().NotBeNull(); - appliesTo.SelfManaged!.Eck.Should().BeEquivalentTo(new Applicability { Lifecycle = Beta, Version = new(3, 0, 2) }); - appliesTo.SelfManaged!.Ece.Should().BeEquivalentTo(new Applicability { Lifecycle = Unavailable }); - appliesTo.SelfManaged!.Stack.Should().BeEquivalentTo(new Applicability { Lifecycle = GenerallyAvailable, Version = new(8, 1, 0) }); - } -} - -public abstract class ParsingTests(ITestOutputHelper output, string moniker, Applicability? expected) - : DirectiveTest(output, -$""" ---- -navigation_title: "Documentation Guide" -applies: - serverless: {moniker} ---- -""" -) -{ - [Fact] - public void Assert() - { - File.YamlFrontMatter.Should().NotBeNull(); - var appliesTo = File.YamlFrontMatter!.AppliesTo; - appliesTo.Should().NotBeNull(); - appliesTo!.Cloud.Should().NotBeNull(); - appliesTo.Cloud!.Serverless.Should().BeEquivalentTo(expected); - } -} - -public class ParsesGa(ITestOutputHelper output) : ParsingTests(output, "ga", new() { Lifecycle = GenerallyAvailable }); -public class ParsesDev(ITestOutputHelper output) : ParsingTests(output, "dev", new() { Lifecycle = Development }); -public class ParsesDevelopment(ITestOutputHelper output) : ParsingTests(output, "development", new() { Lifecycle = Development }); -public class ParsesBeta(ITestOutputHelper output) : ParsingTests(output, "beta", new() { Lifecycle = Beta }); -public class ParsesComing(ITestOutputHelper output) : ParsingTests(output, "coming", new() { Lifecycle = Coming }); -public class ParsesDeprecated(ITestOutputHelper output) : ParsingTests(output, "deprecated", new() { Lifecycle = Deprecated }); -public class ParsesDiscontinued(ITestOutputHelper output) : ParsingTests(output, "discontinued", new() { Lifecycle = Discontinued }); -public class ParsesUnavailable(ITestOutputHelper output) : ParsingTests(output, "unavailable", new() { Lifecycle = Unavailable }); -public class ParsesTechnicalPreview(ITestOutputHelper output) : ParsingTests(output, "tech-preview", new() { Lifecycle = TechnicalPreview }); -public class ParsesPreview(ITestOutputHelper output) : ParsingTests(output, "preview", new() { Lifecycle = TechnicalPreview }); -public class ParsesEmpty(ITestOutputHelper output) : ParsingTests(output, "", Applicability.GenerallyAvailable); -public class ParsesAll(ITestOutputHelper output) : ParsingTests(output, "all", Applicability.GenerallyAvailable); -public class ParsesWithVersion(ITestOutputHelper output) : ParsingTests(output, "ga 7.7.0", new() { Lifecycle = GenerallyAvailable, Version = new(7, 7, 0) }); -public class ParsesWithAllVersion(ITestOutputHelper output) : ParsingTests(output, "ga all", new() { Lifecycle = GenerallyAvailable, Version = AllVersions.Instance }); - -public class CanSpecifyAllForProductVersions(ITestOutputHelper output) : DirectiveTest(output, -""" ---- -navigation_title: "Documentation Guide" -applies: - stack: all ---- -""" -) -{ - [Fact] - public void Assert() => - File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should().BeEquivalentTo(Applicability.GenerallyAvailable); -} - -public class EmptyProductVersionMeansAll(ITestOutputHelper output) : DirectiveTest(output, -""" ---- -navigation_title: "Documentation Guide" -applies: - stack: ---- -""" -) -{ - [Fact] - public void Assert() => - File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should().BeEquivalentTo(Applicability.GenerallyAvailable); -} - -public class EmptyCloudSetsAllCloudProductsToAll(ITestOutputHelper output) : DirectiveTest(output, -""" ---- -navigation_title: "Documentation Guide" -applies: - cloud: ---- -""" -) -{ - [Fact] - public void Assert() => - File.YamlFrontMatter!.AppliesTo!.Cloud!.Hosted.Should().BeEquivalentTo(Applicability.GenerallyAvailable); -} - -public class EmptySelfSetsAllSelfManagedProductsToAll(ITestOutputHelper output) : DirectiveTest(output, -""" ---- -navigation_title: "Documentation Guide" -applies: - self: - stack: deprecated 9.0.0 ---- -""" -) -{ - [Fact] - public void Assert() - { - File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Eck.Should() - .BeEquivalentTo(Applicability.GenerallyAvailable); - File.YamlFrontMatter!.AppliesTo!.SelfManaged!.Stack.Should() - .BeEquivalentTo(new Applicability { Lifecycle = Deprecated, Version = new(9, 0, 0) }); - } -} - -public class CloudProductsOverwriteDeploymentType(ITestOutputHelper output) : DirectiveTest(output, -""" ---- -navigation_title: "Documentation Guide" -applies: - cloud: ---- -""" -) -{ - [Fact] - public void Assert() => - File.YamlFrontMatter!.AppliesTo!.Cloud!.Hosted.Should().BeEquivalentTo(Applicability.GenerallyAvailable); -} - diff --git a/tests/authoring/Framework/MarkdownDocumentAssertions.fs b/tests/authoring/Framework/MarkdownDocumentAssertions.fs index d52bc5216..781d5e8cb 100644 --- a/tests/authoring/Framework/MarkdownDocumentAssertions.fs +++ b/tests/authoring/Framework/MarkdownDocumentAssertions.fs @@ -34,7 +34,7 @@ module MarkdownDocumentAssertions = let matter = result.File.YamlFrontMatter match matter with | NonNull m -> - let apply = m.Apply + let apply = m.AppliesTo test <@ apply = expectedAvailability @> | _ -> failwithf "%s has no yamlfront matter" result.File.RelativePath From 75902a350839b9b029aef4f94dd7f2644b97d8b2 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Tue, 18 Feb 2025 15:12:03 +0100 Subject: [PATCH 5/7] formatting and BOM files cleanup --- docs-builder.sln | 2 +- .../Elastic.Markdown.Refactor.csproj | 2 +- src/Elastic.Markdown/Elastic.Markdown.csproj | 2 +- .../CodeBlocks/EnhancedCodeBlockParser.cs | 8 +++--- .../Myst/FrontMatter/Applicability.cs | 27 ++++++++++--------- .../Myst/FrontMatter/ApplicableTo.cs | 6 ++--- .../Myst/FrontMatter/Deployment.cs | 17 +++++++----- src/docs-assembler/docs-assembler.csproj | 2 +- src/docs-builder/docs-builder.csproj | 2 +- tests/authoring/authoring.fsproj | 2 +- 10 files changed, 40 insertions(+), 30 deletions(-) diff --git a/docs-builder.sln b/docs-builder.sln index 1b00ed9a2..4f2a8e11a 100644 --- a/docs-builder.sln +++ b/docs-builder.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Markdown", "src\Elastic.Markdown\Elastic.Markdown.csproj", "{4D198E25-C211-41DC-9E84-B15E89BD7048}" EndProject diff --git a/src/Elastic.Markdown.Refactor/Elastic.Markdown.Refactor.csproj b/src/Elastic.Markdown.Refactor/Elastic.Markdown.Refactor.csproj index c9bcb3d5f..a42588b61 100644 --- a/src/Elastic.Markdown.Refactor/Elastic.Markdown.Refactor.csproj +++ b/src/Elastic.Markdown.Refactor/Elastic.Markdown.Refactor.csproj @@ -1,4 +1,4 @@ - + net9.0 diff --git a/src/Elastic.Markdown/Elastic.Markdown.csproj b/src/Elastic.Markdown/Elastic.Markdown.csproj index 15b337c15..c4012a4a0 100644 --- a/src/Elastic.Markdown/Elastic.Markdown.csproj +++ b/src/Elastic.Markdown/Elastic.Markdown.csproj @@ -1,4 +1,4 @@ - + net9.0 diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs index 32116e65b..21474e935 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs @@ -31,7 +31,7 @@ protected override EnhancedCodeBlock CreateFencedBlock(BlockProcessor processor) if (processor.Context is not ParserContext context) throw new Exception("Expected parser context to be of type ParserContext"); - var lineSpan = processor.Line.AsSpan(); + var lineSpan = processor.Line.AsSpan(); var codeBlock = lineSpan.IndexOf("{applies_to}") > -1 ? new AppliesToDirective(this, context) { IndentCount = processor.Indent } : new EnhancedCodeBlock(this, context) { IndentCount = processor.Indent }; @@ -116,7 +116,6 @@ private static void ProcessAppliesToDirective(AppliesToDirective appliesToDirect { var applicableTo = YamlSerialization.Deserialize(yaml); appliesToDirective.AppliesTo = applicableTo; - } catch (Exception e) { @@ -162,6 +161,7 @@ private static void ProcessCallOuts(StringLineGroup lines, string language, Enha EnumerateAnnotations(matchClassicCallout, ref span, ref callOutIndex, originatingLine, false) ); } + // only support magic callouts for smaller line lengths if (callOuts.Count == 0 && span.Length < 200) { @@ -170,6 +170,7 @@ private static void ProcessCallOuts(StringLineGroup lines, string language, Enha EnumerateAnnotations(matchInline, ref span, ref callOutIndex, originatingLine, true) ); } + codeBlock.CallOuts.AddRange(callOuts); } @@ -191,7 +192,6 @@ private static void ProcessCallOuts(StringLineGroup lines, string language, Enha var newSpan = line.Slice.AsSpan()[..callout.SliceStart]; var s = new StringSlice(newSpan.ToString()); lines.Lines[callout.Line - 1] = new StringLine(ref s); - } } @@ -263,6 +263,7 @@ private static List ParseClassicCallOuts(ValueMatch match, ref ReadOnly if (span[i] == '<') allStartIndices.Add(i); } + var callOuts = new List(); foreach (var individualStartIndex in allStartIndices) { @@ -281,6 +282,7 @@ private static List ParseClassicCallOuts(ValueMatch match, ref ReadOnly }); } } + return callOuts; } } diff --git a/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs b/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs index 8efb51ab9..69229ab3e 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs @@ -14,7 +14,7 @@ namespace Elastic.Markdown.Myst.FrontMatter; public record ApplicabilityOverTime : IReadOnlyCollection { private readonly IReadOnlyCollection _items; - public ApplicabilityOverTime(Applicability[] items) => _items = items; + private ApplicabilityOverTime(Applicability[] items) => _items = items; // [version] public static bool TryParse(string? value, out ApplicabilityOverTime? availability) @@ -56,14 +56,15 @@ public virtual bool Equals(ApplicabilityOverTime? other) public override int GetHashCode() { var comparer = StructuralComparisons.StructuralEqualityComparer; - return (EqualityComparer.Default.GetHashCode(EqualityContract) * -1521134295) - + comparer.GetHashCode(_items); + return + EqualityComparer.Default.GetHashCode(EqualityContract) * -1521134295 + + comparer.GetHashCode(_items); } public static explicit operator ApplicabilityOverTime(string b) { - var productAvailability = TryParse(b, out var version) ? version : null; + var productAvailability = TryParse(b, out var version) ? version : null; return productAvailability ?? throw new ArgumentException($"'{b}' is not a valid applicability string array."); } @@ -128,7 +129,6 @@ public static explicit operator Applicability(string b) return productAvailability ?? throw new ArgumentException($"'{b}' is not a valid applicability string."); } - // [version] public static bool TryParse(string? value, [NotNullWhen(true)] out Applicability? availability) { if (string.IsNullOrWhiteSpace(value) || string.Equals(value.Trim(), "all", StringComparison.InvariantCultureIgnoreCase)) @@ -143,6 +143,7 @@ public static bool TryParse(string? value, [NotNullWhen(true)] out Applicability availability = null; return false; } + var lifecycle = tokens[0].ToLowerInvariant() switch { "preview" => ProductLifecycle.TechnicalPreview, @@ -158,13 +159,15 @@ public static bool TryParse(string? value, [NotNullWhen(true)] out Applicability _ => throw new ArgumentOutOfRangeException(nameof(tokens), tokens, $"Unknown product lifecycle: {tokens[0]}") }; - var version = tokens.Length < 2 ? null : tokens[1] switch - { - null => AllVersions.Instance, - "all" => AllVersions.Instance, - "" => AllVersions.Instance, - var t => SemVersionConverter.TryParse(t, out var v) ? v : null - }; + var version = tokens.Length < 2 + ? null + : tokens[1] switch + { + null => AllVersions.Instance, + "all" => AllVersions.Instance, + "" => AllVersions.Instance, + var t => SemVersionConverter.TryParse(t, out var v) ? v : null + }; availability = new Applicability { Version = version, Lifecycle = lifecycle }; return true; } diff --git a/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs b/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs index 32b76c22c..f0f241cee 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/ApplicableTo.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information using System.Diagnostics.CodeAnalysis; -using System.Text; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization; @@ -85,6 +84,7 @@ public record ServerlessProjectApplicability Security = ApplicabilityOverTime.GenerallyAvailable }; } + public class ApplicableToConverter : IYamlTypeConverter { public bool Accepts(Type type) => type == typeof(ApplicableTo); @@ -137,7 +137,7 @@ private static void AssignDeploymentType(Dictionary dictionary, Ece = av, Eck = av, Ess = av, - Self = av, + Self = av }; } else if (deploymentType is Dictionary deploymentDictionary) @@ -210,7 +210,7 @@ private static void AssignServerless(Dictionary dictionary, App private static bool TryGetProjectApplicability( Dictionary dictionary, - [NotNullWhen(true)]out ServerlessProjectApplicability? applicability + [NotNullWhen(true)] out ServerlessProjectApplicability? applicability ) { applicability = null; diff --git a/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs b/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs index 75b3dc53b..4d6c1cba6 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/Deployment.cs @@ -9,7 +9,7 @@ namespace Elastic.Markdown.Myst.FrontMatter; [YamlSerializable] -[Obsolete( "Use YamlFrontMatter.Apply instead see also DeploymentMode")] +[Obsolete("Use YamlFrontMatter.Apply instead see also DeploymentMode")] public record Deployment { [YamlMember(Alias = "self")] @@ -26,7 +26,7 @@ public record Deployment } [YamlSerializable] -[Obsolete( "Use YamlFrontMatter.Apply instead")] +[Obsolete("Use YamlFrontMatter.Apply instead")] public record SelfManagedDeployment { [YamlMember(Alias = "stack")] @@ -47,7 +47,7 @@ public record SelfManagedDeployment } [YamlSerializable] -[Obsolete( "Use YamlFrontMatter.Apply instead")] +[Obsolete("Use YamlFrontMatter.Apply instead")] public record CloudManagedDeployment { [YamlMember(Alias = "hosted")] @@ -61,11 +61,10 @@ public record CloudManagedDeployment Hosted = Applicability.GenerallyAvailable, Serverless = Applicability.GenerallyAvailable }; - } #pragma warning disable CS0618 // Type or member is obsolete -[Obsolete( "Use DeploymentAvailability instead" )] +[Obsolete("Use DeploymentAvailability instead")] public class DeploymentConverter : IYamlTypeConverter { public bool Accepts(Type type) => type == typeof(Deployment); @@ -79,6 +78,7 @@ public class DeploymentConverter : IYamlTypeConverter if (string.Equals(value.Value, "all", StringComparison.InvariantCultureIgnoreCase)) return Deployment.All; } + var deserialized = rootDeserializer.Invoke(typeof(Dictionary)); if (deserialized is not Dictionary { Count: > 0 } dictionary) return null; @@ -91,6 +91,7 @@ public class DeploymentConverter : IYamlTypeConverter deployment.Cloud.Serverless = version; deployment.Cloud.Hosted = version; } + if (TryGetAvailability("self", out version)) { deployment.SelfManaged ??= new SelfManagedDeployment(); @@ -104,26 +105,31 @@ public class DeploymentConverter : IYamlTypeConverter deployment.SelfManaged ??= new SelfManagedDeployment(); deployment.SelfManaged.Stack = version; } + if (TryGetAvailability("ece", out version)) { deployment.SelfManaged ??= new SelfManagedDeployment(); deployment.SelfManaged.Ece = version; } + if (TryGetAvailability("eck", out version)) { deployment.SelfManaged ??= new SelfManagedDeployment(); deployment.SelfManaged.Eck = version; } + if (TryGetAvailability("hosted", out version)) { deployment.Cloud ??= new CloudManagedDeployment(); deployment.Cloud.Hosted = version; } + if (TryGetAvailability("serverless", out version)) { deployment.Cloud ??= new CloudManagedDeployment(); deployment.Cloud.Serverless = version; } + return deployment; bool TryGetAvailability(string key, out Applicability? semVersion) @@ -131,7 +137,6 @@ bool TryGetAvailability(string key, out Applicability? semVersion) semVersion = null; return dictionary.TryGetValue(key, out var v) && Applicability.TryParse(v, out semVersion); } - } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) => diff --git a/src/docs-assembler/docs-assembler.csproj b/src/docs-assembler/docs-assembler.csproj index 5caeaa4a2..2c29e96ed 100644 --- a/src/docs-assembler/docs-assembler.csproj +++ b/src/docs-assembler/docs-assembler.csproj @@ -1,4 +1,4 @@ - + net9.0 diff --git a/src/docs-builder/docs-builder.csproj b/src/docs-builder/docs-builder.csproj index b3597c892..16fa62385 100644 --- a/src/docs-builder/docs-builder.csproj +++ b/src/docs-builder/docs-builder.csproj @@ -1,4 +1,4 @@ - + net9.0 diff --git a/tests/authoring/authoring.fsproj b/tests/authoring/authoring.fsproj index 6104b5531..e0a8396d4 100644 --- a/tests/authoring/authoring.fsproj +++ b/tests/authoring/authoring.fsproj @@ -1,4 +1,4 @@ - + net9.0 From f626d1e591e145de734dc9c858d5b12b86b57ff4 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Tue, 18 Feb 2025 15:20:50 +0100 Subject: [PATCH 6/7] fix visibility on constructor --- src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs b/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs index 69229ab3e..1b6a7972d 100644 --- a/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs +++ b/src/Elastic.Markdown/Myst/FrontMatter/Applicability.cs @@ -14,7 +14,7 @@ namespace Elastic.Markdown.Myst.FrontMatter; public record ApplicabilityOverTime : IReadOnlyCollection { private readonly IReadOnlyCollection _items; - private ApplicabilityOverTime(Applicability[] items) => _items = items; + public ApplicabilityOverTime(Applicability[] items) => _items = items; // [version] public static bool TryParse(string? value, out ApplicabilityOverTime? availability) From 5f33fc1af68e862a87df6a3945449198bc714d5c Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Tue, 18 Feb 2025 15:23:43 +0100 Subject: [PATCH 7/7] update {applies} to {applies_to} --- docs/versions/content-patterns.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/versions/content-patterns.md b/docs/versions/content-patterns.md index a0bbb08cd..1ddd2e932 100644 --- a/docs/versions/content-patterns.md +++ b/docs/versions/content-patterns.md @@ -31,12 +31,13 @@ See [Versions and lifecycle states](/versions/index.md#versions-and-lifecycle-st ## Section/heading-level `applies` tags -:::{applies} -:ece: all -:hosted: all -:eck: all -:stack: all -::: +```yaml {applies_to} +stack: ga 9.1 +deployment: + eck: ga 9.0 + ece: discontinued 9.2.0 + self: unavailable 9.3.0 +``` *see [`applies`](/syntax/applies.md#sections)*