From 5d4b0cad545ee8c5e52b9c12a36194f497be669e Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Fri, 11 Jul 2025 13:52:19 +0200 Subject: [PATCH 1/3] Add a page listing recipes by tag --- .../openrewrite/RecipeMarkdownGenerator.kt | 47 +++++++++++++++++++ .../RecipeMarkdownGeneratorTest.kt | 1 + 2 files changed, 48 insertions(+) diff --git a/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt b/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt index 49e8ae65..1b390d27 100644 --- a/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt +++ b/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt @@ -292,6 +292,7 @@ class RecipeMarkdownGenerator : Runnable { createModerneRecipes(outputPath, moderneProprietaryRecipes) createRecipesWithDataTables(recipesWithDataTables, outputPath) createScanningRecipes(allRecipes.filter { it is ScanningRecipe<*> && it !is DeclarativeRecipe }, outputPath) + createRecipesByTag(allRecipeDescriptors, outputPath) // Write the README.md for each category val categories = Category.fromDescriptors(allRecipeDescriptors, allCategoryDescriptors).sortedBy { it.simpleName } @@ -2383,4 +2384,50 @@ $cliSnippet } } } + + private fun createRecipesByTag(allRecipeDescriptors: List, outputPath: Path) { + val tagToRecipes = TreeMap>(String.CASE_INSENSITIVE_ORDER) + + // Collect all tags and their associated recipes + for (recipeDescriptor in allRecipeDescriptors) { + for (tag in recipeDescriptor.tags) { + tagToRecipes.computeIfAbsent(tag) { TreeSet(compareBy { it.name }) } + .add(recipeDescriptor) + } + } + + val markdown = outputPath.resolve("recipes-by-tag.md") + Files.newBufferedWriter(markdown, StandardOpenOption.CREATE).useAndApply { + writeln( + //language=markdown + """ + --- + description: An autogenerated list of all recipe tags and the recipes within each tag. + --- + + # Recipes by Tag + + _This doc contains all recipe tags and the recipes that are tagged with them._ + + """.trimIndent() + ) + + if (tagToRecipes.isEmpty()) { + writeln("No tagged recipes found.") + } else { + writeln("Total tags: ${tagToRecipes.size}\n") + + for ((tag, recipes) in tagToRecipes) { + writeln("## ${tag}") + writeln("\n_${recipes.size} recipe${if (recipes.size != 1) "s" else ""}_\n") + + for (recipe in recipes) { + val displayName = recipe.displayName.replace("`", "") + writeln("* [${displayName}](../recipes/${getRecipePath(recipe)}.md) - _${recipe.description.replace("\n", " ")}_") + } + writeln("") + } + } + } + } } diff --git a/src/test/kotlin/org/openrewrite/RecipeMarkdownGeneratorTest.kt b/src/test/kotlin/org/openrewrite/RecipeMarkdownGeneratorTest.kt index 7530ace1..917b6b10 100644 --- a/src/test/kotlin/org/openrewrite/RecipeMarkdownGeneratorTest.kt +++ b/src/test/kotlin/org/openrewrite/RecipeMarkdownGeneratorTest.kt @@ -25,6 +25,7 @@ class RecipeMarkdownGeneratorTest { "8.x", // Rewrite "2.x", // Recipe BOM + "1.x", // Moderne Recipe BOM "6.x", // Gradle plugin "5.x", // Maven plugin ) From e02dda07d201964e2a3a6856797aa371cdaf8b68 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Fri, 11 Jul 2025 14:49:34 +0200 Subject: [PATCH 2/3] Link to tag page anchor --- src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt b/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt index 1b390d27..4c00127f 100644 --- a/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt +++ b/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt @@ -1126,7 +1126,8 @@ import TabItem from '@theme/TabItem'; } else if (tag.lowercase().startsWith("rspec-")) { writeln("* [$tag](https://sonarsource.github.io/rspec/#/rspec/S${tag.substring(6)})") } else { - writeln("* $tag") + val tagAnchor = tag.lowercase().replace(" ", "-") + writeln("* [$tag](../recipes-by-tag#${tagAnchor})") } } newLine() From a4891a369f83b49b31fd0c2d1ecaab298ce3dd48 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Thu, 24 Jul 2025 00:36:03 +0200 Subject: [PATCH 3/3] Fix botched conflict resolve --- .../openrewrite/RecipeMarkdownGenerator.kt | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt b/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt index 4e9e80f5..d2c93011 100644 --- a/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt +++ b/src/main/kotlin/org/openrewrite/RecipeMarkdownGenerator.kt @@ -2389,7 +2389,7 @@ $cliSnippet private fun createRecipesByTag(allRecipeDescriptors: List, outputPath: Path) { val tagToRecipes = TreeMap>(String.CASE_INSENSITIVE_ORDER) - + // Collect all tags and their associated recipes for (recipeDescriptor in allRecipeDescriptors) { for (tag in recipeDescriptor.tags) { @@ -2397,7 +2397,7 @@ $cliSnippet .add(recipeDescriptor) } } - + val markdown = outputPath.resolve("recipes-by-tag.md") Files.newBufferedWriter(markdown, StandardOpenOption.CREATE).useAndApply { writeln( @@ -2413,21 +2413,29 @@ $cliSnippet """.trimIndent() ) - + if (tagToRecipes.isEmpty()) { writeln("No tagged recipes found.") } else { writeln("Total tags: ${tagToRecipes.size}\n") - + for ((tag, recipes) in tagToRecipes) { writeln("## ${tag}") writeln("\n_${recipes.size} recipe${if (recipes.size != 1) "s" else ""}_\n") - + for (recipe in recipes) { val displayName = recipe.displayName.replace("`", "") - writeln("* [${displayName}](../recipes/${getRecipePath(recipe)}.md) - _${recipe.description.replace("\n", " ")}_") + writeln( + "* [${displayName}](../recipes/${getRecipePath(recipe)}.md) - _${ + recipe.description.replace( + "\n", + " " + ) + }_" + ) } writeln("") + } } } }