diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs
new file mode 100644
index 000000000..d5a71f78b
--- /dev/null
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs
@@ -0,0 +1,13 @@
+// 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.Documentation.AppliesTo;
+
+namespace Elastic.Markdown.Myst.Components;
+
+public record ApplicabilityItem(
+ string Key,
+ Applicability Applicability,
+ ApplicabilityRenderer.ApplicabilityRenderData RenderData
+);
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
new file mode 100644
index 000000000..138b04a0f
--- /dev/null
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
@@ -0,0 +1,57 @@
+// 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.Documentation.Configuration.Versions;
+
+namespace Elastic.Markdown.Myst.Components;
+
+public static class ApplicabilityMappings
+{
+ public record ApplicabilityDefinition(string Key, string DisplayName, VersioningSystemId VersioningSystemId);
+
+ // Stack
+ public static readonly ApplicabilityDefinition Stack = new("Stack", "Elastic Stack", VersioningSystemId.Stack);
+
+ // Serverless
+ public static readonly ApplicabilityDefinition Serverless = new("Serverless", "Elastic Cloud Serverless", VersioningSystemId.Serverless);
+ public static readonly ApplicabilityDefinition ServerlessElasticsearch = new("Serverless Elasticsearch", "Serverless Elasticsearch projects", VersioningSystemId.ElasticsearchProject);
+ public static readonly ApplicabilityDefinition ServerlessObservability = new("Serverless Observability", "Serverless Observability projects", VersioningSystemId.ObservabilityProject);
+ public static readonly ApplicabilityDefinition ServerlessSecurity = new("Serverless Security", "Serverless Security projects", VersioningSystemId.SecurityProject);
+
+ // Deployment
+ public static readonly ApplicabilityDefinition Ech = new("ECH", "Elastic Cloud Hosted", VersioningSystemId.Ess);
+ public static readonly ApplicabilityDefinition Eck = new("ECK", "Elastic Cloud on Kubernetes", VersioningSystemId.Eck);
+ public static readonly ApplicabilityDefinition Ece = new("ECE", "Elastic Cloud Enterprise", VersioningSystemId.Ece);
+ public static readonly ApplicabilityDefinition Self = new("Self-Managed", "Self-managed Elastic deployments", VersioningSystemId.Self);
+
+ // Product Applicability
+ public static readonly ApplicabilityDefinition Ecctl = new("ECCTL", "Elastic Cloud Control", VersioningSystemId.Ecctl);
+ public static readonly ApplicabilityDefinition Curator = new("Curator", "Curator", VersioningSystemId.Curator);
+
+ // EDOT Products
+ public static readonly ApplicabilityDefinition EdotAndroid = new("EDOT Android", "Elastic Distribution of OpenTelemetry Android", VersioningSystemId.EdotAndroid);
+ public static readonly ApplicabilityDefinition EdotCfAws = new("EDOT CF AWS", "Elastic Distribution of OpenTelemetry Cloud Forwarder for AWS", VersioningSystemId.EdotCfAws);
+ public static readonly ApplicabilityDefinition EdotCollector = new("EDOT Collector", "Elastic Distribution of OpenTelemetry Collector", VersioningSystemId.EdotCollector);
+ public static readonly ApplicabilityDefinition EdotDotnet = new("EDOT .NET", "Elastic Distribution of OpenTelemetry .NET", VersioningSystemId.EdotDotnet);
+ public static readonly ApplicabilityDefinition EdotIos = new("EDOT iOS", "Elastic Distribution of OpenTelemetry iOS", VersioningSystemId.EdotIos);
+ public static readonly ApplicabilityDefinition EdotJava = new("EDOT Java", "Elastic Distribution of OpenTelemetry Java", VersioningSystemId.EdotJava);
+ public static readonly ApplicabilityDefinition EdotNode = new("EDOT Node.js", "Elastic Distribution of OpenTelemetry Node.js", VersioningSystemId.EdotNode);
+ public static readonly ApplicabilityDefinition EdotPhp = new("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.EdotPhp);
+ public static readonly ApplicabilityDefinition EdotPython = new("EDOT Python", "Elastic Distribution of OpenTelemetry Python", VersioningSystemId.EdotPython);
+
+ // APM Agents
+ public static readonly ApplicabilityDefinition ApmAgentAndroid = new("APM Agent Android", "Application Performance Monitoring Agent for Android", VersioningSystemId.ApmAgentAndroid);
+ public static readonly ApplicabilityDefinition ApmAgentDotnet = new("APM Agent .NET", "Application Performance Monitoring Agent for .NET", VersioningSystemId.ApmAgentDotnet);
+ public static readonly ApplicabilityDefinition ApmAgentGo = new("APM Agent Go", "Application Performance Monitoring Agent for Go", VersioningSystemId.ApmAgentGo);
+ public static readonly ApplicabilityDefinition ApmAgentIos = new("APM Agent iOS", "Application Performance Monitoring Agent for iOS", VersioningSystemId.ApmAgentIos);
+ public static readonly ApplicabilityDefinition ApmAgentJava = new("APM Agent Java", "Application Performance Monitoring Agent for Java", VersioningSystemId.ApmAgentJava);
+ public static readonly ApplicabilityDefinition ApmAgentNode = new("APM Agent Node.js", "Application Performance Monitoring Agent for Node.js", VersioningSystemId.ApmAgentNode);
+ public static readonly ApplicabilityDefinition ApmAgentPhp = new("APM Agent PHP", "Application Performance Monitoring Agent for PHP", VersioningSystemId.ApmAgentPhp);
+ public static readonly ApplicabilityDefinition ApmAgentPython = new("APM Agent Python", "Application Performance Monitoring Agent for Python", VersioningSystemId.ApmAgentPython);
+ public static readonly ApplicabilityDefinition ApmAgentRuby = new("APM Agent Ruby", "Application Performance Monitoring Agent for Ruby", VersioningSystemId.ApmAgentRuby);
+ public static readonly ApplicabilityDefinition ApmAgentRum = new("APM Agent RUM", "Application Performance Monitoring Agent for Real User Monitoring", VersioningSystemId.ApmAgentRum);
+
+ // Generic product
+ public static readonly ApplicabilityDefinition Product = new("", "", VersioningSystemId.All);
+}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
new file mode 100644
index 000000000..87a683c89
--- /dev/null
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
@@ -0,0 +1,141 @@
+// 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 Elastic.Documentation;
+using Elastic.Documentation.AppliesTo;
+using Elastic.Documentation.Configuration.Versions;
+
+namespace Elastic.Markdown.Myst.Components;
+
+public class ApplicabilityRenderer
+{
+ public record ApplicabilityRenderData(
+ string BadgeLifecycleText,
+ string Version,
+ string TooltipText,
+ string LifecycleClass,
+ bool ShowLifecycleName,
+ bool ShowVersion
+ );
+
+ public ApplicabilityRenderData RenderApplicability(
+ Applicability applicability,
+ ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
+ VersioningSystem versioningSystem,
+ AppliesCollection allApplications)
+ {
+ var lifecycleClass = applicability.GetLifeCycleName().ToLowerInvariant().Replace(" ", "-");
+ var lifecycleFull = GetLifecycleFullText(applicability.Lifecycle);
+ var realVersion = TryGetRealVersion(applicability, out var v) ? v : null;
+
+ var tooltipText = BuildTooltipText(applicability, applicabilityDefinition, versioningSystem, realVersion, lifecycleFull);
+ var badgeLifecycleText = BuildBadgeLifecycleText(applicability, versioningSystem, realVersion, allApplications);
+
+ var showLifecycle = applicability.Lifecycle != ProductLifecycle.GenerallyAvailable && string.IsNullOrEmpty(badgeLifecycleText);
+ var showVersion = applicability.Version is not null and not AllVersions && versioningSystem.Current >= applicability.Version;
+ var version = applicability.Version?.ToString() ?? "";
+ return new ApplicabilityRenderData(
+ BadgeLifecycleText: badgeLifecycleText,
+ Version: version,
+ TooltipText: tooltipText,
+ LifecycleClass: lifecycleClass,
+ ShowLifecycleName: showLifecycle,
+ ShowVersion: showVersion
+ );
+ }
+
+ private static string GetLifecycleFullText(ProductLifecycle lifecycle) => lifecycle switch
+ {
+ ProductLifecycle.GenerallyAvailable => "Available",
+ ProductLifecycle.Beta => "Available in beta",
+ ProductLifecycle.TechnicalPreview => "Available in technical preview",
+ ProductLifecycle.Deprecated => "Deprecated",
+ ProductLifecycle.Removed => "Removed",
+ ProductLifecycle.Unavailable => "Not available",
+ _ => ""
+ };
+
+ private static string BuildTooltipText(
+ Applicability applicability,
+ ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
+ VersioningSystem versioningSystem,
+ SemVersion? realVersion,
+ string lifecycleFull)
+ {
+ var tooltipText = "";
+
+ tooltipText = realVersion is not null
+ ? realVersion <= versioningSystem.Current
+ ? $"{lifecycleFull} on {applicabilityDefinition.DisplayName} version {realVersion} and later unless otherwise specified."
+ : applicability.Lifecycle switch
+ {
+ ProductLifecycle.GenerallyAvailable
+ or ProductLifecycle.Beta
+ or ProductLifecycle.TechnicalPreview
+ or ProductLifecycle.Planned =>
+ $"We plan to add this functionality in a future {applicabilityDefinition.DisplayName} update. Subject to change.",
+ ProductLifecycle.Deprecated => $"We plan to deprecate this functionality in a future {applicabilityDefinition.DisplayName} update. Subject to change.",
+ ProductLifecycle.Removed => $"We plan to remove this functionality in a future {applicabilityDefinition.DisplayName} update. Subject to change.",
+ _ => tooltipText
+ }
+ : $"{lifecycleFull} on {applicabilityDefinition.DisplayName} unless otherwise specified.";
+
+ var disclaimer = GetDisclaimer(applicability.Lifecycle, versioningSystem.Id);
+ if (disclaimer is not null)
+ tooltipText = $"{tooltipText}\n\n{disclaimer}";
+
+ return tooltipText;
+ }
+
+ private static string? GetDisclaimer(ProductLifecycle lifecycle, VersioningSystemId versioningSystemId) => lifecycle switch
+ {
+ ProductLifecycle.Beta => "Beta features are subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.",
+ ProductLifecycle.TechnicalPreview => "This functionality may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.",
+ ProductLifecycle.GenerallyAvailable => versioningSystemId is VersioningSystemId.Stack
+ ? "If this functionality is unavailable or behaves differently when deployed on ECH, ECE, ECK, or a self-managed installation, it will be indicated on the page."
+ : null,
+ _ => null
+ };
+
+ private static string BuildBadgeLifecycleText(
+ Applicability applicability,
+ VersioningSystem versioningSystem,
+ SemVersion? realVersion,
+ AppliesCollection allApplications)
+ {
+ var badgeText = "";
+ if (realVersion is not null && realVersion > versioningSystem.Current)
+ {
+ badgeText = applicability.Lifecycle switch
+ {
+ ProductLifecycle.TechnicalPreview => "Planned",
+ ProductLifecycle.Beta => "Planned",
+ ProductLifecycle.GenerallyAvailable =>
+ allApplications.Any(a => a.Lifecycle is ProductLifecycle.TechnicalPreview or ProductLifecycle.Beta)
+ ? "GA planned"
+ : "Planned",
+ ProductLifecycle.Deprecated => "Deprecation planned",
+ ProductLifecycle.Removed => "Removal planned",
+ ProductLifecycle.Planned => "Planned",
+ ProductLifecycle.Unavailable => "Unavailable",
+ _ => badgeText
+ };
+ }
+
+ return badgeText;
+ }
+
+ private static bool TryGetRealVersion(Applicability applicability, [NotNullWhen(true)] out SemVersion? version)
+ {
+ version = null;
+ if (applicability.Version is not null && applicability.Version != AllVersions.Instance)
+ {
+ version = applicability.Version;
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
index a8960aad9..f35d221e9 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
@@ -1,357 +1,29 @@
-@using System.Diagnostics.CodeAnalysis
-@using Elastic.Documentation
-@using Elastic.Documentation.AppliesTo
-@using Elastic.Documentation.Configuration.Versions
@inherits RazorSlice
-@{
- var appliesTo = Model.AppliesTo;
-}
-
-@if (appliesTo.Stack is not null)
-{
- @RenderProduct(
- "Stack",
- "Elastic Stack",
- VersioningSystemId.Stack,
- appliesTo.Stack
- )
-}
-@if (appliesTo.Serverless is not null)
-{
- if (appliesTo.Serverless.AllProjects is not null)
- {
- @RenderProduct(
- "Serverless",
- "Elastic Cloud Serverless",
- VersioningSystemId.Serverless,
- appliesTo.Serverless.AllProjects
- )
- }
- else
- {
- if (appliesTo.Serverless.Elasticsearch is not null)
- {
- @RenderProduct(
- "Serverless Elasticsearch",
- "Serverless Elasticsearch projects",
- VersioningSystemId.ElasticsearchProject,
- appliesTo.Serverless.Elasticsearch
- )
- }
-
- if (appliesTo.Serverless.Observability is not null)
- {
- @RenderProduct(
- "Serverless Observability",
- "Serverless Observability projects",
- VersioningSystemId.ObservabilityProject,
- appliesTo.Serverless.Observability
- )
- }
-
- if (appliesTo.Serverless.Security is not null)
- {
- @RenderProduct(
- "Serverless Security",
- "Serverless Security projects",
- VersioningSystemId.SecurityProject,
- appliesTo.Serverless.Security
- )
- }
- }
-}
-@if (appliesTo.Deployment is not null)
-{
-
- if (appliesTo.Deployment.Ess is not null)
- {
- @RenderProduct(
- "ECH",
- "Elastic Cloud Hosted",
- VersioningSystemId.Ess,
- appliesTo.Deployment.Ess
- )
- }
-
- if (appliesTo.Deployment.Eck is not null)
- {
- @RenderProduct(
- "ECK",
- "Elastic Cloud on Kubernetes",
- VersioningSystemId.Eck,
- appliesTo.Deployment.Eck
- )
- }
-
- if (appliesTo.Deployment.Ece is not null)
- {
- @RenderProduct("ECE",
- "Elastic Cloud Enterprise",
- VersioningSystemId.Ece,
- appliesTo.Deployment.Ece
- )
- }
-
- if (appliesTo.Deployment.Self is not null)
- {
- @RenderProduct(
- "Self-Managed",
- "Self-managed Elastic deployments",
- VersioningSystemId.Self,
- appliesTo.Deployment.Self
- )
- }
-}
-@if (appliesTo.ProductApplicability is not null)
-{
- var pa = appliesTo.ProductApplicability;
- if (pa.Ecctl is not null)
- {
- @RenderProduct("ECCTL", "Elastic Cloud Control", VersioningSystemId.Ecctl, pa.Ecctl)
- }
-
- if (pa.Curator is not null)
- {
- @RenderProduct("Curator", "Curator", VersioningSystemId.Curator, pa.Curator)
- }
-
- if (pa.EdotAndroid is not null)
- {
- @RenderProduct("EDOT Android", "Elastic Distribution of OpenTelemetry Android", VersioningSystemId.EdotAndroid, pa.EdotAndroid)
- }
-
- if (pa.EdotCfAws is not null)
- {
- @RenderProduct("EDOT CF AWS", "Elastic Distribution of OpenTelemetry Cloud Forwarder for AWS", VersioningSystemId.EdotCfAws, pa.EdotCfAws)
- }
-
- if (pa.EdotCollector is not null)
- {
- @RenderProduct("EDOT Collector", "Elastic Distribution of OpenTelemetry Collector", VersioningSystemId.EdotCollector, pa.EdotCollector)
- }
-
- if (pa.EdotDotnet is not null)
- {
- @RenderProduct("EDOT .NET", "Elastic Distribution of OpenTelemetry .NET", VersioningSystemId.EdotDotnet, pa.EdotDotnet)
- }
-
- if (pa.EdotIos is not null)
- {
- @RenderProduct("EDOT iOS", "Elastic Distribution of OpenTelemetry iOS", VersioningSystemId.EdotIos, pa.EdotIos)
- }
-
- if (pa.EdotJava is not null)
- {
- @RenderProduct("EDOT Java", "Elastic Distribution of OpenTelemetry Java", VersioningSystemId.EdotJava, pa.EdotJava)
- }
-
- if (pa.EdotNode is not null)
- {
- @RenderProduct("EDOT Node.js", "Elastic Distribution of OpenTelemetry Node.js", VersioningSystemId.EdotNode, pa.EdotNode)
- }
-
- if (pa.EdotPhp is not null)
- {
- @RenderProduct("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.ApmAgentPhp, pa.EdotPhp)
- }
-
- if (pa.EdotPython is not null)
- {
- @RenderProduct("EDOT Python", "Elastic Distribution of OpenTelemetry Python", VersioningSystemId.EdotPython, pa.EdotPython)
- }
-
- if (pa.ApmAgentAndroid is not null)
- {
- @RenderProduct("APM Agent Android", "Application Performance Monitoring Agent for Android", VersioningSystemId.ApmAgentAndroid, pa.ApmAgentAndroid)
- }
-
- if (pa.ApmAgentDotnet is not null)
- {
- @RenderProduct("APM Agent .NET", "Application Performance Monitoring Agent for .NET", VersioningSystemId.ApmAgentDotnet, pa.ApmAgentDotnet)
- }
-
- if (pa.ApmAgentGo is not null)
- {
- @RenderProduct("APM Agent Go", "Application Performance Monitoring Agent for Go", VersioningSystemId.ApmAgentGo, pa.ApmAgentGo)
- }
-
- if (pa.ApmAgentIos is not null)
- {
- @RenderProduct("APM Agent iOS", "Application Performance Monitoring Agent for iOS", VersioningSystemId.ApmAgentIos, pa.ApmAgentIos)
- }
-
- if (pa.ApmAgentJava is not null)
- {
- @RenderProduct("APM Agent Java", "Application Performance Monitoring Agent for Java", VersioningSystemId.ApmAgentJava, pa.ApmAgentJava)
- }
-
- if (pa.ApmAgentNode is not null)
- {
- @RenderProduct("APM Agent Node.js", "Application Performance Monitoring Agent for Node.js", VersioningSystemId.ApmAgentNode, pa.ApmAgentNode)
- }
-
- if (pa.ApmAgentPhp is not null)
- {
- @RenderProduct("APM Agent PHP", "Application Performance Monitoring Agent for PHP", VersioningSystemId.ApmAgentPhp, pa.ApmAgentPhp)
- }
-
- if (pa.ApmAgentPython is not null)
- {
- @RenderProduct("APM Agent Python", "Application Performance Monitoring Agent for Python", VersioningSystemId.ApmAgentPython, pa.ApmAgentPython)
- }
-
- if (pa.ApmAgentRuby is not null)
- {
- @RenderProduct("APM Agent Ruby", "Application Performance Monitoring Agent for Ruby", VersioningSystemId.ApmAgentRuby, pa.ApmAgentRuby)
- }
-
- if (pa.ApmAgentRum is not null)
- {
- @RenderProduct("APM Agent RUM", "Application Performance Monitoring Agent for Real User Monitoring", VersioningSystemId.ApmAgentRum, pa.ApmAgentRum)
- }
-}
-@if (appliesTo.Product is not null)
+@foreach (var item in Model.GetApplicabilityItems())
{
- @RenderProduct("", "", VersioningSystemId.All, appliesTo.Product)
-}
-
-@functions {
-
- private IHtmlContent RenderProduct(string key, string keyFull, VersioningSystemId versioningSystemName, AppliesCollection applications)
- {
- var versioningSystem = Model.VersionsConfig.GetVersioningSystem(versioningSystemName);
-
- foreach (var applicability in applications)
- {
- var badgeText = key;
- var tooltipText = "";
- var lifecycleClass = applicability.GetLifeCycleName().ToLowerInvariant().Replace(" ", "-");
+
+ @item.Key
- var lifecycleFull = applicability.Lifecycle switch
+ @if (!string.IsNullOrEmpty(item.Key) && (item.RenderData.ShowLifecycleName || item.RenderData.ShowVersion || !string.IsNullOrEmpty(item.RenderData.BadgeLifecycleText)))
{
- ProductLifecycle.GenerallyAvailable => "Available",
- ProductLifecycle.Beta => "Available in beta",
- ProductLifecycle.TechnicalPreview => "Available in technical preview",
- ProductLifecycle.Deprecated => "Deprecated",
- ProductLifecycle.Removed => "Removed",
- ProductLifecycle.Unavailable => "Not available",
- _ => ""
- };
-
- var realVersion = TryGetRealVersion(applicability, out var v) ? v : null;
-
- if (realVersion is not null)
- {
-
- if (realVersion <= versioningSystem.Current)
+
+ }
+
+ @if (item.RenderData.ShowLifecycleName)
{
- tooltipText = $"{lifecycleFull} on {keyFull} version {realVersion} and later unless otherwise specified.";
+ @item.Applicability.GetLifeCycleName()
}
- else
+ @if (item.RenderData.ShowVersion)
{
- tooltipText = applicability.Lifecycle switch
- {
- ProductLifecycle.GenerallyAvailable
- or ProductLifecycle.Beta
- or ProductLifecycle.TechnicalPreview
- or ProductLifecycle.Planned =>
- $"We plan to add this functionality in a future {keyFull} update. Subject to change.",
- ProductLifecycle.Deprecated => $"We plan to deprecate this functionality in a future {keyFull} update. Subject to change.",
- ProductLifecycle.Removed => $"We plan to remove this functionality in a future {keyFull} update. Subject to change.",
- _ => tooltipText
- };
+
+ @item.RenderData.Version
+
}
-
- }
- else
- {
- tooltipText = $"{lifecycleFull} on {keyFull} unless otherwise specified.";
- }
-
- var disclaimer = applicability.Lifecycle switch
- {
- ProductLifecycle.Beta => "Beta features are subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.",
- ProductLifecycle.TechnicalPreview => "This functionality may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.",
- ProductLifecycle.GenerallyAvailable => versioningSystem.Id is VersioningSystemId.Stack ? "If this functionality is unavailable or behaves differently when deployed on ECH, ECE, ECK, or a self-managed installation, it will be indicated on the page." : null,
- _ => null
- };
-
- if (disclaimer is not null)
- {
- tooltipText = $"{tooltipText}\n\n{disclaimer}";
- }
-
- if (realVersion is not null && realVersion > versioningSystem.Current)
- {
- badgeText = applicability.Lifecycle switch
- {
- ProductLifecycle.TechnicalPreview => "Planned",
- ProductLifecycle.Beta => "Planned",
- ProductLifecycle.GenerallyAvailable =>
- applications.Any(a => a.Lifecycle is ProductLifecycle.TechnicalPreview or ProductLifecycle.Beta)
- ? "GA planned"
- : "Planned",
- ProductLifecycle.Deprecated => "Deprecation planned",
- ProductLifecycle.Removed => "Removal planned",
- ProductLifecycle.Planned => "Planned",
- _ => badgeText
- };
- }
-
- var badgeTextChanged = badgeText != key;
-
- @key
-
- @{
- var showLifeCycle = applicability.Lifecycle != ProductLifecycle.GenerallyAvailable && !badgeTextChanged;
- var showVersion = applicability.Version is not null and not AllVersions;
- }
-
- @if (!string.IsNullOrEmpty(key) && (showLifeCycle || showVersion))
+ else
{
-
+ @item.RenderData.BadgeLifecycleText
}
-
- @if (showLifeCycle)
- {
- @applicability.GetLifeCycleName()
- }
- @if (showVersion)
- {
- @if (versioningSystem.Current >= applicability.Version!)
- {
-
- @applicability.Version
-
- }
- else
- {
- @badgeText
- }
- }
-
- }
-
- return HtmlString.Empty;
- }
-
-}
-
-@functions {
-
- private static bool TryGetRealVersion(Applicability applicability, [NotNullWhen(true)] out SemVersion? version)
- {
- version = null;
- if (applicability.Version is not null && applicability.Version != AllVersions.Instance)
- {
- version = applicability.Version;
- return true;
- }
-
- return false;
- }
-
+
}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
index 103226fb7..ef50735ab 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
@@ -9,7 +9,127 @@ namespace Elastic.Markdown.Myst.Components;
public class ApplicableToViewModel
{
+ private readonly ApplicabilityRenderer _applicabilityRenderer = new();
+
public required bool Inline { get; init; }
public required ApplicableTo AppliesTo { get; init; }
public required VersionsConfiguration VersionsConfig { get; init; }
+
+ // Dictionary mapping property selectors to their applicability definitions
+ private static readonly Dictionary, ApplicabilityMappings.ApplicabilityDefinition> DeploymentMappings = new()
+ {
+ [d => d.Ess] = ApplicabilityMappings.Ech,
+ [d => d.Eck] = ApplicabilityMappings.Eck,
+ [d => d.Ece] = ApplicabilityMappings.Ece,
+ [d => d.Self] = ApplicabilityMappings.Self
+ };
+
+ private static readonly Dictionary, ApplicabilityMappings.ApplicabilityDefinition> ServerlessMappings = new()
+ {
+ [s => s.Elasticsearch] = ApplicabilityMappings.ServerlessElasticsearch,
+ [s => s.Observability] = ApplicabilityMappings.ServerlessObservability,
+ [s => s.Security] = ApplicabilityMappings.ServerlessSecurity
+ };
+
+ private static readonly Dictionary, ApplicabilityMappings.ApplicabilityDefinition> ProductMappings = new()
+ {
+ [p => p.Ecctl] = ApplicabilityMappings.Ecctl,
+ [p => p.Curator] = ApplicabilityMappings.Curator,
+ [p => p.EdotAndroid] = ApplicabilityMappings.EdotAndroid,
+ [p => p.EdotCfAws] = ApplicabilityMappings.EdotCfAws,
+ [p => p.EdotCollector] = ApplicabilityMappings.EdotCollector,
+ [p => p.EdotDotnet] = ApplicabilityMappings.EdotDotnet,
+ [p => p.EdotIos] = ApplicabilityMappings.EdotIos,
+ [p => p.EdotJava] = ApplicabilityMappings.EdotJava,
+ [p => p.EdotNode] = ApplicabilityMappings.EdotNode,
+ [p => p.EdotPhp] = ApplicabilityMappings.EdotPhp,
+ [p => p.EdotPython] = ApplicabilityMappings.EdotPython,
+ [p => p.ApmAgentAndroid] = ApplicabilityMappings.ApmAgentAndroid,
+ [p => p.ApmAgentDotnet] = ApplicabilityMappings.ApmAgentDotnet,
+ [p => p.ApmAgentGo] = ApplicabilityMappings.ApmAgentGo,
+ [p => p.ApmAgentIos] = ApplicabilityMappings.ApmAgentIos,
+ [p => p.ApmAgentJava] = ApplicabilityMappings.ApmAgentJava,
+ [p => p.ApmAgentNode] = ApplicabilityMappings.ApmAgentNode,
+ [p => p.ApmAgentPhp] = ApplicabilityMappings.ApmAgentPhp,
+ [p => p.ApmAgentPython] = ApplicabilityMappings.ApmAgentPython,
+ [p => p.ApmAgentRuby] = ApplicabilityMappings.ApmAgentRuby,
+ [p => p.ApmAgentRum] = ApplicabilityMappings.ApmAgentRum
+ };
+
+ public IEnumerable GetApplicabilityItems()
+ {
+ var items = new List();
+
+ // Process Stack
+ if (AppliesTo.Stack is not null)
+ items.AddRange(ProcessSingleCollection(AppliesTo.Stack, ApplicabilityMappings.Stack));
+
+ // Process Serverless
+ if (AppliesTo.Serverless is not null)
+ {
+ items.AddRange(AppliesTo.Serverless.AllProjects is not null
+ ? ProcessSingleCollection(AppliesTo.Serverless.AllProjects, ApplicabilityMappings.Serverless)
+ : ProcessMappedCollections(AppliesTo.Serverless, ServerlessMappings));
+ }
+
+ // Process Deployment
+ if (AppliesTo.Deployment is not null)
+ items.AddRange(ProcessMappedCollections(AppliesTo.Deployment, DeploymentMappings));
+
+ // Process Product Applicability
+ if (AppliesTo.ProductApplicability is not null)
+ items.AddRange(ProcessMappedCollections(AppliesTo.ProductApplicability, ProductMappings));
+
+ // Process Generic Product
+ if (AppliesTo.Product is not null)
+ items.AddRange(ProcessSingleCollection(AppliesTo.Product, ApplicabilityMappings.Product));
+
+ return items;
+ }
+
+ ///
+ /// Processes a single collection with its corresponding applicability definition
+ ///
+ private IEnumerable ProcessSingleCollection(AppliesCollection collection, ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition)
+ {
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDefinition.VersioningSystemId);
+ return ProcessApplicabilityCollection(collection, applicabilityDefinition, versioningSystem);
+ }
+
+ ///
+ /// Processes multiple collections using a mapping dictionary to eliminate repetitive code
+ ///
+ private IEnumerable ProcessMappedCollections(T source, Dictionary, ApplicabilityMappings.ApplicabilityDefinition> mappings)
+ {
+ var items = new List();
+
+ foreach (var (propertySelector, applicabilityDefinition) in mappings)
+ {
+ var collection = propertySelector(source);
+ if (collection is not null)
+ items.AddRange(ProcessSingleCollection(collection, applicabilityDefinition));
+ }
+
+ return items;
+ }
+
+ private IEnumerable ProcessApplicabilityCollection(
+ AppliesCollection applications,
+ ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
+ VersioningSystem versioningSystem) =>
+ applications.Select(applicability =>
+ {
+ var renderData = _applicabilityRenderer.RenderApplicability(
+ applicability,
+ applicabilityDefinition,
+ versioningSystem,
+ applications);
+
+ return new ApplicabilityItem(
+ Key: applicabilityDefinition.Key,
+ Applicability: applicability,
+ RenderData: renderData
+ );
+ });
+
}
diff --git a/tests/authoring/Applicability/ApplicableToComponent.fs b/tests/authoring/Applicability/ApplicableToComponent.fs
index 7a8b50357..fc6c07223 100644
--- a/tests/authoring/Applicability/ApplicableToComponent.fs
+++ b/tests/authoring/Applicability/ApplicableToComponent.fs
@@ -507,6 +507,32 @@ product: ga
"""
+
+type ``product preview`` () =
+ static let markdown = Setup.Markdown """
+```{applies_to}
+product: preview 1.3.0
+```
+"""
+
+ []
+ let ``renders product preview`` () =
+ markdown |> convertsToHtml """
+
+
+
+
+ Preview
+
+ 1.3.0
+
+
+
+
+"""
+
// Test complex mixed scenarios
type ``complex mixed scenario`` () =