From c3121091b578f06b961ffca79a1a930c12593106 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Wed, 30 Jul 2025 22:28:00 +0200 Subject: [PATCH 01/10] Add subs to stepper headings --- src/Elastic.Markdown/IO/MarkdownFile.cs | 24 +++++++++++++------ .../Myst/Directives/Stepper/StepperBlock.cs | 4 ++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Elastic.Markdown/IO/MarkdownFile.cs b/src/Elastic.Markdown/IO/MarkdownFile.cs index 6e1c21eec..19c33c1a0 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -289,15 +289,25 @@ public static List GetAnchors( .OfType() .Where(step => !string.IsNullOrEmpty(step.Title)) .Where(step => !IsNestedInOtherDirective(step)) - .Select(step => new + .Select(step => { - TocItem = new PageTocItem + var processedTitle = step.Title; + // Apply substitutions to step titles + if (subs.Count > 0 && processedTitle.AsSpan().ReplaceSubstitutions(subs, set.Context.Collector, out var replacement)) { - Heading = step.Title, - Slug = step.Anchor, - Level = step.HeadingLevel // Use dynamic heading level - }, - step.Line + processedTitle = replacement; + } + + return new + { + TocItem = new PageTocItem + { + Heading = processedTitle, + Slug = step.Anchor, + Level = step.HeadingLevel // Use dynamic heading level + }, + step.Line + }; }); var toc = headingTocs diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs index 4f8645ff0..52f4c8358 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs @@ -26,6 +26,10 @@ public class StepBlock(DirectiveBlockParser parser, ParserContext context) : Dir public override void FinalizeAndValidate(ParserContext context) { Title = Arguments ?? string.Empty; + + // Apply substitutions to the title + Title = Title.ReplaceSubstitutions(context); + Anchor = Prop("anchor") ?? Title.Slugify(); // Calculate heading level based on preceding heading From 86e7110ce4cfeeaef0710c3b960e2f43b1063b5d Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Wed, 30 Jul 2025 22:30:41 +0200 Subject: [PATCH 02/10] Docs sample --- docs/_docset.yml | 1 + docs/contribute/locally.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_docset.yml b/docs/_docset.yml index 8ab198efe..31b325c65 100644 --- a/docs/_docset.yml +++ b/docs/_docset.yml @@ -16,6 +16,7 @@ subs: ech: "Elastic Cloud Hosted" serverless-full: "Elastic Cloud Serverless" ecloud: "Elastic Cloud" + dbuild: "docs-builder" features: primary-nav: false diff --git a/docs/contribute/locally.md b/docs/contribute/locally.md index 15d1ce815..e1cb48ab2 100644 --- a/docs/contribute/locally.md +++ b/docs/contribute/locally.md @@ -145,7 +145,7 @@ cd docs-content ``` ::::: -:::::{step} Run docs-builder +:::::{step} Run {{dbuild}} Run the `docs-builder` binary with the `serve` command to build and serve the content set to [http://localhost:3000](http://localhost:3000). If necessary, specify the path to the `docset.yml` file that you want to build with `-p`. From ec3c10c82aa54529ba027a8a169aa9becf89b6ec Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 10:27:34 +0200 Subject: [PATCH 03/10] Use renderer --- .../Myst/Directives/Stepper/StepView.cshtml | 12 ++++++------ .../Myst/Directives/Stepper/StepViewModel.cs | 12 ++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepView.cshtml b/src/Elastic.Markdown/Myst/Directives/Stepper/StepView.cshtml index e6712b38c..78f2d698d 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepView.cshtml +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepView.cshtml @@ -6,32 +6,32 @@ { case 1:

- @Model.Title + @Model.RenderTitle()

break; case 2:

- @Model.Title + @Model.RenderTitle()

break; case 3:

- @Model.Title + @Model.RenderTitle()

break; case 4:

- @Model.Title + @Model.RenderTitle()

break; case 5:
- @Model.Title + @Model.RenderTitle()
break; default:
- @Model.Title + @Model.RenderTitle()
break; } diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index 2efcb442e..e760fec6d 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -2,6 +2,8 @@ // 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 Microsoft.AspNetCore.Html; + namespace Elastic.Markdown.Myst.Directives.Stepper; public class StepViewModel : DirectiveViewModel @@ -9,4 +11,14 @@ public class StepViewModel : DirectiveViewModel public required string Title { get; init; } public required string Anchor { get; init; } public required int HeadingLevel { get; init; } + + /// + /// Renders the title with substitutions applied + /// + public HtmlString RenderTitle() + { + // For now, just return the title as-is since substitutions are already applied in FinalizeAndValidate + // In the future, this could be extended to handle full markdown processing + return new HtmlString(Title); + } } From 76f056cecc617a1332fdd2d85ca36cab6f136c43 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 10:29:10 +0200 Subject: [PATCH 04/10] Fix linter warning --- .../Myst/Directives/Stepper/StepViewModel.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index e760fec6d..c8a2e31e1 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -15,10 +15,5 @@ public class StepViewModel : DirectiveViewModel /// /// Renders the title with substitutions applied /// - public HtmlString RenderTitle() - { - // For now, just return the title as-is since substitutions are already applied in FinalizeAndValidate - // In the future, this could be extended to handle full markdown processing - return new HtmlString(Title); - } + public HtmlString RenderTitle() => new HtmlString(Title); } From f610780e18d5560df029712d32abade982302f4c Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 10:29:42 +0200 Subject: [PATCH 05/10] Fix another warning --- src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index c8a2e31e1..ef0d6de96 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -15,5 +15,5 @@ public class StepViewModel : DirectiveViewModel /// /// Renders the title with substitutions applied /// - public HtmlString RenderTitle() => new HtmlString(Title); + public HtmlString RenderTitle() => new(Title); } From 055f622b9768957e5922ef1363a9def00c1ff758 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 11:08:32 +0200 Subject: [PATCH 06/10] Use Markdig --- .../Myst/Directives/Stepper/StepViewModel.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index ef0d6de96..8622cc8a1 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -2,6 +2,9 @@ // 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 Markdig.Syntax; +using Markdig.Syntax.Inlines; using Microsoft.AspNetCore.Html; namespace Elastic.Markdown.Myst.Directives.Stepper; @@ -13,7 +16,10 @@ public class StepViewModel : DirectiveViewModel public required int HeadingLevel { get; init; } /// - /// Renders the title with substitutions applied + /// Renders the title with full markdown processing (substitutions, links, emphasis, etc.) /// - public HtmlString RenderTitle() => new(Title); + public HtmlString RenderTitle() => + // For now, just return the title as-is since substitutions are already applied in FinalizeAndValidate + // In the future, this could be extended to handle full markdown processing using the HTML renderer + new(Title); } From 31e6d29dc9808770d27819a342769ac0ba4cc542 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 11:13:35 +0200 Subject: [PATCH 07/10] Proper renderer --- .../Myst/Directives/Stepper/StepViewModel.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index 8622cc8a1..db269a8c5 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -18,8 +18,22 @@ public class StepViewModel : DirectiveViewModel /// /// Renders the title with full markdown processing (substitutions, links, emphasis, etc.) /// - public HtmlString RenderTitle() => - // For now, just return the title as-is since substitutions are already applied in FinalizeAndValidate - // In the future, this could be extended to handle full markdown processing using the HTML renderer - new(Title); + public HtmlString RenderTitle() + { + // Parse the title as markdown inline content + var document = Markdig.Markdown.Parse(Title, MarkdownParser.Pipeline); + var firstBlock = document.FirstOrDefault() as Markdig.Syntax.ParagraphBlock; + var inline = firstBlock?.Inline; + + if (firstBlock == null) + return new(Title); + + // Use the HTML renderer to render the inline content with full processing + var subscription = DocumentationObjectPoolProvider.HtmlRendererPool.Get(); + _ = subscription.HtmlRenderer.WriteLeafInline(firstBlock); + + var result = subscription.RentedStringBuilder?.ToString() ?? Title; + DocumentationObjectPoolProvider.HtmlRendererPool.Return(subscription); + return new(result); + } } From a65dc7123ab23475eb3cbbe8637b035eb1dec5b1 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 11:28:55 +0200 Subject: [PATCH 08/10] Move subs logic --- .../Myst/Directives/Stepper/StepViewModel.cs | 18 +++++++++++------- .../Myst/Directives/Stepper/StepperBlock.cs | 3 --- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index db269a8c5..7d044f960 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -20,19 +20,23 @@ public class StepViewModel : DirectiveViewModel /// public HtmlString RenderTitle() { - // Parse the title as markdown inline content - var document = Markdig.Markdown.Parse(Title, MarkdownParser.Pipeline); - var firstBlock = document.FirstOrDefault() as Markdig.Syntax.ParagraphBlock; - var inline = firstBlock?.Inline; + // Apply substitutions first, then parse with Markdig + var directiveBlock = (DirectiveBlock)DirectiveBlock; + var span = Title.AsSpan(); + var processedTitle = span.ReplaceSubstitutions(directiveBlock.Build.Configuration.Substitutions, directiveBlock.Build.Collector, out var replacement) + ? replacement : Title; - if (firstBlock == null) - return new(Title); + // Parse the processed title as markdown inline content + var document = Markdig.Markdown.Parse(processedTitle, MarkdownParser.Pipeline); + + if (document.FirstOrDefault() is not Markdig.Syntax.ParagraphBlock firstBlock) + return new(processedTitle); // Use the HTML renderer to render the inline content with full processing var subscription = DocumentationObjectPoolProvider.HtmlRendererPool.Get(); _ = subscription.HtmlRenderer.WriteLeafInline(firstBlock); - var result = subscription.RentedStringBuilder?.ToString() ?? Title; + var result = subscription.RentedStringBuilder?.ToString() ?? processedTitle; DocumentationObjectPoolProvider.HtmlRendererPool.Return(subscription); return new(result); } diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs index 52f4c8358..e539c8376 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepperBlock.cs @@ -27,9 +27,6 @@ public override void FinalizeAndValidate(ParserContext context) { Title = Arguments ?? string.Empty; - // Apply substitutions to the title - Title = Title.ReplaceSubstitutions(context); - Anchor = Prop("anchor") ?? Title.Slugify(); // Calculate heading level based on preceding heading From 3e37dc01d2cd1f82be2aa1f9460cf1113d7cab21 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 11:31:25 +0200 Subject: [PATCH 09/10] Clean up --- .../Myst/Directives/Stepper/StepViewModel.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index 7d044f960..65a04ddd1 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -20,23 +20,26 @@ public class StepViewModel : DirectiveViewModel /// public HtmlString RenderTitle() { - // Apply substitutions first, then parse with Markdig + // Parse the title as markdown with full pipeline (including substitutions) var directiveBlock = (DirectiveBlock)DirectiveBlock; - var span = Title.AsSpan(); - var processedTitle = span.ReplaceSubstitutions(directiveBlock.Build.Configuration.Substitutions, directiveBlock.Build.Collector, out var replacement) - ? replacement : Title; + var context = new ParserContext(new ParserState(directiveBlock.Build) + { + MarkdownSourcePath = directiveBlock.CurrentFile, + YamlFrontMatter = null, + DocumentationFileLookup = (path) => null!, + CrossLinkResolver = null! + }); - // Parse the processed title as markdown inline content - var document = Markdig.Markdown.Parse(processedTitle, MarkdownParser.Pipeline); + var document = Markdig.Markdown.Parse(Title, MarkdownParser.Pipeline, context); if (document.FirstOrDefault() is not Markdig.Syntax.ParagraphBlock firstBlock) - return new(processedTitle); + return new(Title); // Use the HTML renderer to render the inline content with full processing var subscription = DocumentationObjectPoolProvider.HtmlRendererPool.Get(); _ = subscription.HtmlRenderer.WriteLeafInline(firstBlock); - var result = subscription.RentedStringBuilder?.ToString() ?? processedTitle; + var result = subscription.RentedStringBuilder?.ToString() ?? Title; DocumentationObjectPoolProvider.HtmlRendererPool.Return(subscription); return new(result); } From a6a673fd60179bc3e7f56fcfe40ec81608ed5e25 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri Benedetti Date: Fri, 1 Aug 2025 12:12:35 +0200 Subject: [PATCH 10/10] Rewrite part --- .../Myst/Directives/Stepper/StepViewModel.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs index 65a04ddd1..b7f17cdd8 100644 --- a/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs +++ b/src/Elastic.Markdown/Myst/Directives/Stepper/StepViewModel.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information using Elastic.Markdown.Helpers; +using Elastic.Markdown.IO; using Markdig.Syntax; using Markdig.Syntax.Inlines; using Microsoft.AspNetCore.Html; @@ -22,10 +23,15 @@ public HtmlString RenderTitle() { // Parse the title as markdown with full pipeline (including substitutions) var directiveBlock = (DirectiveBlock)DirectiveBlock; + + // Get the YamlFrontMatter from the original document to support local substitutions + var originalContext = directiveBlock.GetData("context") as ParserContext; + var yamlFrontMatter = originalContext?.YamlFrontMatter; + var context = new ParserContext(new ParserState(directiveBlock.Build) { MarkdownSourcePath = directiveBlock.CurrentFile, - YamlFrontMatter = null, + YamlFrontMatter = yamlFrontMatter, DocumentationFileLookup = (path) => null!, CrossLinkResolver = null! });