From a3d796768c723dd29065c4ec6a1fe1a3af115cf7 Mon Sep 17 00:00:00 2001 From: shainaraskas Date: Fri, 19 Jun 2026 10:23:27 -0400 Subject: [PATCH 1/4] fix(applies-to): avoid weird "Removed Planned" multi-lifecycle badge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the highest-version lifecycle in a multi-lifecycle applies_to was unreleased (e.g. `stack: deprecated, removed 10.0` with current 9.4.2), the catch-all fallback synthesised "Planned" badge text but left ShowLifecycleName=true, so the badge rendered the lifecycle name ("Removed") and the forced text ("Planned") side by side. Honour the documented "use previous lifecycle" rule: when the highest candidate is future/unreleased, prefer a lower-version applicability that is current or has no version (so `stack: deprecated, removed 10.0` now renders as "Stack | Deprecated"). Only fall back to a synthesised "Removal planned"/"Deprecation planned"/"Planned" label — with ShowLifecycleName=false — when every applicability is unreleased. Closes #3537 Co-Authored-By: Claude Opus 4.7 Co-authored-by: Cursor --- .../Myst/Components/ApplicabilityRenderer.cs | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs index cc04a86e4..4f4af86f2 100644 --- a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs +++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs @@ -78,14 +78,37 @@ public static ApplicabilityRenderData RenderApplicability( } } - // If we've exhausted all options (none had displayable data), use the first one. - // Only show "Planned" when the first applicability is actually future/unreleased (has a version spec that is not yet released). - // When the first applicability has no version (null/AllVersionsSpec), it means GA for all versions - keep badge text empty. + // If we've exhausted all options (none had displayable data), pick a fallback. + // When the highest-version applicability is future/unreleased, prefer the "previous lifecycle" + // (a lower-version applicability that is current or has no version) over a synthesized "Planned" badge. + // This avoids weird renderings like "Removed Planned" for `deprecated, removed X` where X is unreleased. if (badgeData is null && firstBadgeData is not null && firstApplicability is not null && versioningSystem.IsVersioned()) { var versionSpec = firstApplicability.Version; var isFutureVersion = versionSpec is not null && versionSpec != AllVersionsSpec.Instance && versionSpec.Min > versioningSystem.Current; - badgeData = isFutureVersion ? firstBadgeData with { BadgeLifecycleText = "Planned" } : firstBadgeData; + + if (isFutureVersion) + { + var previousLifecycle = sortedApplicabilities.FirstOrDefault(a => + a != firstApplicability && + (a.Version is null || a.Version == AllVersionsSpec.Instance || + a.Version.Min <= versioningSystem.Current)); + + if (previousLifecycle is not null) + badgeData = GetBadgeData(previousLifecycle, versioningSystem, allApplications); + else + { + var fallbackText = firstApplicability.Lifecycle switch + { + ProductLifecycle.Deprecated => "Deprecation planned", + ProductLifecycle.Removed => "Removal planned", + _ => "Planned" + }; + badgeData = firstBadgeData with { BadgeLifecycleText = fallbackText, ShowLifecycleName = false }; + } + } + else + badgeData = firstBadgeData; } badgeData ??= GetBadgeData(sortedApplicabilities.First(), versioningSystem, allApplications); From 4c1e17ab0cc2af1ddcaa29aa8a6b2486bc8c82ff Mon Sep 17 00:00:00 2001 From: shainaraskas <58563081+shainaraskas@users.noreply.github.com> Date: Fri, 19 Jun 2026 10:39:47 -0400 Subject: [PATCH 2/4] Update src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs --- src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs index 4f4af86f2..baace5269 100644 --- a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs +++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs @@ -81,7 +81,6 @@ public static ApplicabilityRenderData RenderApplicability( // If we've exhausted all options (none had displayable data), pick a fallback. // When the highest-version applicability is future/unreleased, prefer the "previous lifecycle" // (a lower-version applicability that is current or has no version) over a synthesized "Planned" badge. - // This avoids weird renderings like "Removed Planned" for `deprecated, removed X` where X is unreleased. if (badgeData is null && firstBadgeData is not null && firstApplicability is not null && versioningSystem.IsVersioned()) { var versionSpec = firstApplicability.Version; From 63c3caf4cca8a29f5a2b71b6994056eb28e163a4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:44:01 +0000 Subject: [PATCH 3/4] docs(applies-to): restore applicability fallback comment nuance --- src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs index baace5269..6d8858010 100644 --- a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs +++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs @@ -81,6 +81,8 @@ public static ApplicabilityRenderData RenderApplicability( // If we've exhausted all options (none had displayable data), pick a fallback. // When the highest-version applicability is future/unreleased, prefer the "previous lifecycle" // (a lower-version applicability that is current or has no version) over a synthesized "Planned" badge. + // This keeps combinations like `deprecated, removed 10.0` from rendering as "Removed Planned" + // when the removal version is still unreleased. if (badgeData is null && firstBadgeData is not null && firstApplicability is not null && versioningSystem.IsVersioned()) { var versionSpec = firstApplicability.Version; From add93db684b698d2314eaed7307f68637ef43b90 Mon Sep 17 00:00:00 2001 From: shainaraskas <58563081+shainaraskas@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:03:15 -0400 Subject: [PATCH 4/4] Update src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs --- src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs index 6d8858010..baace5269 100644 --- a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs +++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs @@ -81,8 +81,6 @@ public static ApplicabilityRenderData RenderApplicability( // If we've exhausted all options (none had displayable data), pick a fallback. // When the highest-version applicability is future/unreleased, prefer the "previous lifecycle" // (a lower-version applicability that is current or has no version) over a synthesized "Planned" badge. - // This keeps combinations like `deprecated, removed 10.0` from rendering as "Removed Planned" - // when the removal version is still unreleased. if (badgeData is null && firstBadgeData is not null && firstApplicability is not null && versioningSystem.IsVersioned()) { var versionSpec = firstApplicability.Version;