$ show LikeTheSalad/android-stem
Android Stem is a Gradle plugin that resolves placeholders in Android XML string resource files at compile time. It scans `res/values/` directories (and library dependencies) for strings containing placeholders like `${app_name}`, then replaces them with actual values defined in other strings. The plugin supports multi-language (`values-es/`, `values-fr/`), multi-flavor (product flavors), and recursive template resolution with circular dependency detection. It integrates with the Android Gradle Plugin (AGP) variant API, registering three cacheable tasks per build variant: `RawStringCollector` (collects all string resources into a protobuf binary), `GatherStringTemplates` (identifies templates and their values, outputting JSON), and `ResolvePlaceholders` (performs the actual placeholder substitution and writes resolved XML files to `build/generated/stem/`). The plugin is configured via an `androidStem` block in `build.gradle.kts`, allowing customization of placeholder delimiters and localized-only template inclusion. It is published on the Gradle Plugin Portal and has a comprehensive test suite covering unit, integration, and concurrency scenarios.
The LLM identified 3 files worth highlighting for reuse:
Implements a non-trivial algorithm to order templates by their recursive dependency level before resolution. It detects circular dependencies and groups templates so that lower-level templates (those with no placeholders) are resolved first, then their values are used to resolve higher-level templates. This pattern is reusable in any template engine that needs to handle nested placeholders safely.
Collects string resources from multiple resource directories (app and library dependencies), merging them by value directory name (e.g., 'values', 'values-es'). It detects duplicate string names within the same value directory and throws an error, ensuring data integrity. The collection logic is parameterized and could be extracted for any XML-based resource aggregation task.
Provides thread-safe XML parsing utilities for extracting text content from DOM nodes while preserving inner HTML tags (e.g., `<b>`). The concurrency fix (issue #332) ensures that shared `DocumentBuilder` and `Transformer` instances are not reused across threads, a common pitfall in multi-threaded XML processing. The `getContents` method is a reusable pattern for extracting inner XML text without outer tags.