|
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