Skip to content

Commit 6a52ba9

Browse files
authored
Add docset products attribute (#1239)
1 parent be20456 commit 6a52ba9

File tree

10 files changed

+139
-87
lines changed

10 files changed

+139
-87
lines changed

docs/_docset.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ subs:
1313
serverless-short: Serverless
1414
ece: "Elastic Cloud Enterprise"
1515
eck: "Elastic Cloud on Kubernetes"
16+
17+
products:
18+
- elasticsearch
1619

1720
features:
1821
primary-nav: false

docs/syntax/code.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
---
2+
products:
3+
- apm
4+
---
5+
16
# Code
27

38
Code blocks can be used to display multiple lines of code. They preserve formatting and provide syntax highlighting when possible.

src/Elastic.Documentation.Configuration/Builder/ConfigurationFile.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System.IO.Abstractions;
66
using DotNet.Globbing;
7+
using Elastic.Documentation.Configuration.Suggestions;
78
using Elastic.Documentation.Configuration.TableOfContents;
89
using Elastic.Documentation.Links;
910
using Elastic.Documentation.Navigation;
@@ -33,6 +34,8 @@ public record ConfigurationFile : ITableOfContentsScope
3334

3435
public Dictionary<string, LinkRedirect>? Redirects { get; }
3536

37+
public HashSet<string> Products { get; } = new(StringComparer.Ordinal);
38+
3639
public HashSet<string> ImplicitFolders { get; } = new(StringComparer.OrdinalIgnoreCase);
3740

3841
public Glob[] Globs { get; } = [];
@@ -104,6 +107,20 @@ public ConfigurationFile(IDocumentationContext context)
104107
case "toc":
105108
// read this later
106109
break;
110+
case "products":
111+
var productIds = YamlStreamReader.ReadStringArray(entry.Entry);
112+
foreach (var productId in productIds)
113+
{
114+
if (!Builder.Products.AllById.ContainsKey(productId))
115+
{
116+
var message =
117+
$"Product \"{productId}\" not found in the product list. {new Suggestion(Builder.Products.All.Select(p => p.Id).ToHashSet(), productId).GetSuggestionQuestion()}";
118+
reader.EmitError(message, entry.Entry.Value);
119+
}
120+
else
121+
_ = Products.Add(productId);
122+
}
123+
break;
107124
case "features":
108125
_features = reader.ReadDictionary(entry.Entry).ToDictionary(k => k.Key, v => bool.Parse(v.Value), StringComparer.OrdinalIgnoreCase);
109126
break;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Collections.Frozen;
6+
7+
namespace Elastic.Documentation.Configuration.Builder;
8+
9+
public record Product(string Id, string DisplayName);
10+
11+
public static class Products
12+
{
13+
public static FrozenSet<Product> All { get; } = [
14+
new("apm", "APM"),
15+
new("apm-dotnet-agent", "APM .NET Agent"),
16+
new("apm-android-agent", "APM Android Agent"),
17+
new("apm-attacher", "APM Attacher"),
18+
new("apm-aws-lambda-extension", "APM AWS Lambda extension"),
19+
new("apm-go-agent", "APM Go Agent"),
20+
new("apm-ios-agent", "APM iOS Agent"),
21+
new("apm-java-agent", "APM Java Agent"),
22+
new("apm-node-agent", "APM Node.js Agent"),
23+
new("apm-php-agent", "APM PHP Agent"),
24+
new("apm-python-agent", "APM Python Agent"),
25+
new("apm-ruby-agent", "APM Ruby Agent"),
26+
new("apm-rum-agent", "APM RUM Agent"),
27+
new("beats-logging-plugin", "Beats Logging plugin"),
28+
new("cloud-control-ecctl", "Cloud Control ECCTL"),
29+
new("cloud-enterprise", "Cloud Enterprise"),
30+
new("cloud-hosted", "Cloud Hosted"),
31+
new("cloud-kubernetes", "Cloud Kubernetes"),
32+
new("cloud-native-ingest", "Cloud Native Ingest"),
33+
new("cloud-serverless", "Cloud Serverless"),
34+
new("cloud-terraform", "Cloud Terraform"),
35+
new("ecs-logging", "ECS Logging"),
36+
new("ecs-logging-dotnet", "ECS Logging .NET"),
37+
new("ecs-logging-go-logrus", "ECS Logging Go Logrus"),
38+
new("ecs-logging-go-zap", "ECS Logging Go Zap"),
39+
new("ecs-logging-go-zerolog", "ECS Logging Go Zerolog"),
40+
new("ecs-logging-java", "ECS Logging Java"),
41+
new("ecs-logging-node", "ECS Logging Node.js"),
42+
new("ecs-logging-php", "ECS Logging PHP"),
43+
new("ecs-logging-python", "ECS Logging Python"),
44+
new("ecs-logging-ruby", "ECS Logging Ruby"),
45+
new("elastic-agent", "Elastic Agent"),
46+
new("ecs", "Elastic Common Schema (ECS)"),
47+
new("elastic-products-platform", "Elastic Products platform"),
48+
new("elastic-stack", "Elastic Stack"),
49+
new("elasticsearch", "Elasticsearch"),
50+
new("elasticsearch-dotnet-client", "Elasticsearch .NET Client"),
51+
new("elasticsearch-apache-hadoop", "Elasticsearch Apache Hadoop"),
52+
new("elasticsearch-cloud-hosted-heroku", "Elasticsearch Cloud Hosted Heroku"),
53+
new("elasticsearch-community-clients", "Elasticsearch community clients"),
54+
new("elasticsearch-curator", "Elasticsearch Curator"),
55+
new("elasticsearch-eland-python-client", "Elasticsearch Eland Python Client"),
56+
new("elasticsearch-go-client", "Elasticsearch Go Client"),
57+
new("elasticsearch-groovy-client", "Elasticsearch Groovy Client"),
58+
new("elasticsearch-java-client", "Elasticsearch Java Client"),
59+
new("elasticsearch-java-script-client", "Elasticsearch JavaScript Client"),
60+
new("elasticsearch-painless-scripting-language", "Elasticsearch Painless scripting language"),
61+
new("elasticsearch-perl-client", "Elasticsearch Perl Client"),
62+
new("elasticsearch-php-client", "Elasticsearch PHP Client"),
63+
new("elasticsearch-plugins", "Elasticsearch plugins"),
64+
new("elasticsearch-python-client", "Elasticsearch Python Client"),
65+
new("elasticsearch-resiliency-status", "Elasticsearch Resiliency Status"),
66+
new("elasticsearch-ruby-client", "Elasticsearch Ruby Client"),
67+
new("elasticsearch-rust-client", "Elasticsearch Rust Client"),
68+
new("fleet", "Fleet"),
69+
new("ingest", "Ingest"),
70+
new("integrations", "Integrations"),
71+
new("kibana", "Kibana"),
72+
new("logstash", "Logstash"),
73+
new("machine-learning", "Machine Learning"),
74+
new("observability", "Observability"),
75+
new("reference-architectures", "Reference Architectures"),
76+
new("search-ui", "Search UI"),
77+
new("security", "Security"),
78+
new("edot-collector", "Elastic Distribution of OpenTelemetry Collector"),
79+
new("edot-java", "Elastic Distribution of OpenTelemetry Java"),
80+
new("edot-dotnet", "Elastic Distribution of OpenTelemetry .NET"),
81+
new("edot-nodejs", "Elastic Distribution of OpenTelemetry Node.js"),
82+
new("edot-php", "Elastic Distribution of OpenTelemetry PHP"),
83+
new("edot-python", "Elastic Distribution of OpenTelemetry Python"),
84+
new("edot-android", "Elastic Distribution of OpenTelemetry Android"),
85+
new("edot-ios", "Elastic Distribution of OpenTelemetry iOS")
86+
];
87+
88+
public static FrozenDictionary<string, Product> AllById { get; } = All.ToDictionary(p => p.Id, StringComparer.Ordinal).ToFrozenDictionary();
89+
}

src/Elastic.Markdown/Suggestions/Suggestions.cs renamed to src/Elastic.Documentation.Configuration/Suggestions/Suggestions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5-
namespace Elastic.Markdown.Suggestions;
5+
namespace Elastic.Documentation.Configuration.Suggestions;
66

77
public class Suggestion(IReadOnlySet<string> candidates, string input)
88
{

src/Elastic.Markdown/Myst/FrontMatter/FrontMatterParser.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using Elastic.Documentation.Configuration.Builder;
56
using YamlDotNet.Serialization;
67

78
namespace Elastic.Markdown.Myst.FrontMatter;

src/Elastic.Markdown/Myst/FrontMatter/Products.cs

Lines changed: 2 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -3,96 +3,14 @@
33
// See the LICENSE file in the project root for more information
44

55
using System.Collections.Frozen;
6-
using System.ComponentModel.DataAnnotations;
7-
using Elastic.Markdown.Suggestions;
6+
using Elastic.Documentation.Configuration.Builder;
7+
using Elastic.Documentation.Configuration.Suggestions;
88
using YamlDotNet.Core;
99
using YamlDotNet.Core.Events;
1010
using YamlDotNet.Serialization;
1111

1212
namespace Elastic.Markdown.Myst.FrontMatter;
1313

14-
public record Product(string Id, string DisplayName);
15-
16-
public static class Products
17-
{
18-
public static FrozenSet<Product> All { get; } = [
19-
new("apm", "APM"),
20-
new("apm-dotnet-agent", "APM .NET Agent"),
21-
new("apm-android-agent", "APM Android Agent"),
22-
new("apm-attacher", "APM Attacher"),
23-
new("apm-aws-lambda-extension", "APM AWS Lambda extension"),
24-
new("apm-go-agent", "APM Go Agent"),
25-
new("apm-ios-agent", "APM iOS Agent"),
26-
new("apm-java-agent", "APM Java Agent"),
27-
new("apm-node-agent", "APM Node.js Agent"),
28-
new("apm-php-agent", "APM PHP Agent"),
29-
new("apm-python-agent", "APM Python Agent"),
30-
new("apm-ruby-agent", "APM Ruby Agent"),
31-
new("apm-rum-agent", "APM RUM Agent"),
32-
new("beats-logging-plugin", "Beats Logging plugin"),
33-
new("cloud-control-ecctl", "Cloud Control ECCTL"),
34-
new("cloud-enterprise", "Cloud Enterprise"),
35-
new("cloud-hosted", "Cloud Hosted"),
36-
new("cloud-kubernetes", "Cloud Kubernetes"),
37-
new("cloud-native-ingest", "Cloud Native Ingest"),
38-
new("cloud-serverless", "Cloud Serverless"),
39-
new("cloud-terraform", "Cloud Terraform"),
40-
new("ecs-logging", "ECS Logging"),
41-
new("ecs-logging-dotnet", "ECS Logging .NET"),
42-
new("ecs-logging-go-logrus", "ECS Logging Go Logrus"),
43-
new("ecs-logging-go-zap", "ECS Logging Go Zap"),
44-
new("ecs-logging-go-zerolog", "ECS Logging Go Zerolog"),
45-
new("ecs-logging-java", "ECS Logging Java"),
46-
new("ecs-logging-node", "ECS Logging Node.js"),
47-
new("ecs-logging-php", "ECS Logging PHP"),
48-
new("ecs-logging-python", "ECS Logging Python"),
49-
new("ecs-logging-ruby", "ECS Logging Ruby"),
50-
new("elastic-agent", "Elastic Agent"),
51-
new("ecs", "Elastic Common Schema (ECS)"),
52-
new("elastic-products-platform", "Elastic Products platform"),
53-
new("elastic-stack", "Elastic Stack"),
54-
new("elasticsearch", "Elasticsearch"),
55-
new("elasticsearch-dotnet-client", "Elasticsearch .NET Client"),
56-
new("elasticsearch-apache-hadoop", "Elasticsearch Apache Hadoop"),
57-
new("elasticsearch-cloud-hosted-heroku", "Elasticsearch Cloud Hosted Heroku"),
58-
new("elasticsearch-community-clients", "Elasticsearch community clients"),
59-
new("elasticsearch-curator", "Elasticsearch Curator"),
60-
new("elasticsearch-eland-python-client", "Elasticsearch Eland Python Client"),
61-
new("elasticsearch-go-client", "Elasticsearch Go Client"),
62-
new("elasticsearch-groovy-client", "Elasticsearch Groovy Client"),
63-
new("elasticsearch-java-client", "Elasticsearch Java Client"),
64-
new("elasticsearch-java-script-client", "Elasticsearch JavaScript Client"),
65-
new("elasticsearch-painless-scripting-language", "Elasticsearch Painless scripting language"),
66-
new("elasticsearch-perl-client", "Elasticsearch Perl Client"),
67-
new("elasticsearch-php-client", "Elasticsearch PHP Client"),
68-
new("elasticsearch-plugins", "Elasticsearch plugins"),
69-
new("elasticsearch-python-client", "Elasticsearch Python Client"),
70-
new("elasticsearch-resiliency-status", "Elasticsearch Resiliency Status"),
71-
new("elasticsearch-ruby-client", "Elasticsearch Ruby Client"),
72-
new("elasticsearch-rust-client", "Elasticsearch Rust Client"),
73-
new("fleet", "Fleet"),
74-
new("ingest", "Ingest"),
75-
new("integrations", "Integrations"),
76-
new("kibana", "Kibana"),
77-
new("logstash", "Logstash"),
78-
new("machine-learning", "Machine Learning"),
79-
new("observability", "Observability"),
80-
new("reference-architectures", "Reference Architectures"),
81-
new("search-ui", "Search UI"),
82-
new("security", "Security"),
83-
new("edot-collector", "Elastic Distribution of OpenTelemetry Collector"),
84-
new("edot-java", "Elastic Distribution of OpenTelemetry Java"),
85-
new("edot-dotnet", "Elastic Distribution of OpenTelemetry .NET"),
86-
new("edot-nodejs", "Elastic Distribution of OpenTelemetry Node.js"),
87-
new("edot-php", "Elastic Distribution of OpenTelemetry PHP"),
88-
new("edot-python", "Elastic Distribution of OpenTelemetry Python"),
89-
new("edot-android", "Elastic Distribution of OpenTelemetry Android"),
90-
new("edot-ios", "Elastic Distribution of OpenTelemetry iOS")
91-
];
92-
93-
public static FrozenDictionary<string, Product> AllById { get; } = All.ToDictionary(p => p.Id, StringComparer.Ordinal).ToFrozenDictionary();
94-
}
95-
9614
public class ProductConverter : IYamlTypeConverter
9715
{
9816
public bool Accepts(Type type) => type == typeof(Product);

src/Elastic.Markdown/Slices/HtmlWriter.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
using System.Collections.Concurrent;
66
using System.IO.Abstractions;
77
using Elastic.Documentation;
8+
using Elastic.Documentation.Configuration.Builder;
89
using Elastic.Documentation.Legacy;
910
using Elastic.Markdown.Extensions.DetectionRules;
1011
using Elastic.Markdown.IO;
1112
using Elastic.Markdown.IO.Navigation;
13+
using Elastic.Markdown.Myst.FrontMatter;
1214
using Markdig.Syntax;
1315
using RazorSlices;
1416
using IFileInfo = System.IO.Abstractions.IFileInfo;
@@ -115,6 +117,20 @@ private async Task<string> RenderLayout(MarkdownFile markdown, MarkdownDocument
115117

116118
var legacyPage = LegacyUrlMapper.MapLegacyUrl(markdown.YamlFrontMatter?.MappedPages);
117119

120+
var configProducts = DocumentationSet.Configuration.Products.Select(p =>
121+
{
122+
if (Products.AllById.TryGetValue(p, out var product))
123+
return product;
124+
throw new ArgumentException($"Invalid product id: {p}");
125+
});
126+
127+
var frontMatterProducts = markdown.YamlFrontMatter?.Products ?? [];
128+
129+
var allProducts = frontMatterProducts
130+
.Union(configProducts)
131+
.Distinct()
132+
.ToHashSet();
133+
118134
var slice = Index.Create(new IndexViewModel
119135
{
120136
SiteName = siteName,
@@ -139,7 +155,8 @@ private async Task<string> RenderLayout(MarkdownFile markdown, MarkdownDocument
139155
Features = DocumentationSet.Configuration.Features,
140156
StaticFileContentHashProvider = StaticFileContentHashProvider,
141157
ReportIssueUrl = reportUrl,
142-
LegacyPage = legacyPage
158+
LegacyPage = legacyPage,
159+
Products = allProducts
143160
});
144161
return await slice.RenderAsync(cancellationToken: ctx);
145162
}

src/Elastic.Markdown/Slices/Index.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
StaticFileContentHashProvider = Model.StaticFileContentHashProvider,
2424
ReportIssueUrl = Model.ReportIssueUrl,
2525
LegacyPage = Model.LegacyPage,
26-
Products = Model.CurrentDocument.YamlFrontMatter?.Products is { Count: > 0} products ? string.Join(",", products.Select(p => p.DisplayName)) : null,
26+
Products = Model.Products is { Count: > 0} products ? string.Join(",", products.Select(p => p.DisplayName)) : null,
2727
};
2828
}
2929
<section id="elastic-docs-v3">

src/Elastic.Markdown/Slices/_ViewModels.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public class IndexViewModel
3939

4040
public required FeatureFlags Features { get; init; }
4141
public required StaticFileContentHashProvider StaticFileContentHashProvider { get; init; }
42+
43+
public required HashSet<Product> Products { get; init; }
4244
}
4345

4446
public class LayoutViewModel

0 commit comments

Comments
 (0)