|
2 | 2 | // Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
3 | 3 | // See the LICENSE file in the project root for more information
|
4 | 4 |
|
| 5 | +using System.Collections.Frozen; |
5 | 6 | using System.ComponentModel.DataAnnotations;
|
| 7 | +using Elastic.Markdown.Suggestions; |
6 | 8 | using EnumFastToStringGenerated;
|
7 | 9 | using YamlDotNet.Core;
|
8 | 10 | using YamlDotNet.Core.Events;
|
@@ -255,57 +257,12 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
|
255 | 257 | public class InvalidProductException(string invalidValue)
|
256 | 258 | : Exception(
|
257 | 259 | $"Invalid products frontmatter value: \"{invalidValue}\"." +
|
258 |
| - (!string.IsNullOrWhiteSpace(invalidValue) ? $" Did you mean \"{ProductExtensions.Suggestion(invalidValue)}\"?" : "") + |
| 260 | + (!string.IsNullOrWhiteSpace(invalidValue) ? " " + new Suggestion(ProductExtensions.GetProductIds(), invalidValue).GetSuggestionQuestion() : "") + |
259 | 261 | "\nYou can find the full list at https://docs-v3-preview.elastic.dev/elastic/docs-builder/tree/main/syntax/frontmatter#products.");
|
260 | 262 |
|
261 | 263 | public static class ProductExtensions
|
262 | 264 | {
|
263 |
| - private static IReadOnlyCollection<string> GetProductIds() => |
| 265 | + public static IReadOnlySet<string> GetProductIds() => |
264 | 266 | ProductEnumExtensions.GetValuesFast()
|
265 |
| - .Select(p => p.ToDisplayFast()).ToList(); |
266 |
| - |
267 |
| - public static string Suggestion(string input) => |
268 |
| - GetProductIds() |
269 |
| - .OrderBy(p => LevenshteinDistance(input, p)) |
270 |
| - .First(); |
271 |
| - |
272 |
| - // Based on https://rosettacode.org/wiki/Levenshtein_distance#C# |
273 |
| - private static int LevenshteinDistance(string input, string product) |
274 |
| - { |
275 |
| - if (string.IsNullOrEmpty(product)) |
276 |
| - return int.MaxValue; |
277 |
| - |
278 |
| - var inputLength = input.Length; |
279 |
| - var productLength = product.Length; |
280 |
| - |
281 |
| - if (inputLength == 0) |
282 |
| - return productLength; |
283 |
| - |
284 |
| - if (productLength == 0) |
285 |
| - return inputLength; |
286 |
| - |
287 |
| - var distance = new int[inputLength + 1, productLength + 1]; |
288 |
| - |
289 |
| - for (var i = 0; i <= inputLength; i++) |
290 |
| - distance[i, 0] = i; |
291 |
| - |
292 |
| - for (var j = 0; j <= productLength; j++) |
293 |
| - distance[0, j] = j; |
294 |
| - |
295 |
| - for (var i = 1; i <= inputLength; i++) |
296 |
| - { |
297 |
| - for (var j = 1; j <= productLength; j++) |
298 |
| - { |
299 |
| - var cost = (input[i - 1] == product[j - 1]) ? 0 : 1; |
300 |
| - |
301 |
| - distance[i, j] = Math.Min( |
302 |
| - Math.Min( |
303 |
| - distance[i - 1, j] + 1, |
304 |
| - distance[i, j - 1] + 1), |
305 |
| - distance[i - 1, j - 1] + cost); |
306 |
| - } |
307 |
| - } |
308 |
| - |
309 |
| - return distance[inputLength, productLength]; |
310 |
| - } |
| 267 | + .Select(p => p.ToDisplayFast()).ToFrozenSet(); |
311 | 268 | }
|
0 commit comments