diff --git a/scripts/BUILD.bazel b/scripts/BUILD.bazel index 9577dfe834b..ee4fb13c930 100644 --- a/scripts/BUILD.bazel +++ b/scripts/BUILD.bazel @@ -312,3 +312,10 @@ java_binary( main_class = "org.oppia.android.scripts.telemetry.DecodeUserStudyEventStringKt", runtime_deps = ["//scripts/src/java/org/oppia/android/scripts/telemetry:decode_user_study_event_string_lib"], ) + +kt_jvm_binary( + name = "check_textview_styles", + testonly = True, + main_class = "org.oppia.android.scripts.xml.TextViewStyleCheckKt", + runtime_deps = ["//scripts/src/java/org/oppia/android/scripts/xml:check_textview_styles"], +) diff --git a/scripts/src/java/org/oppia/android/scripts/xml/BUILD.bazel b/scripts/src/java/org/oppia/android/scripts/xml/BUILD.bazel index 0657b000c49..6b29905f078 100644 --- a/scripts/src/java/org/oppia/android/scripts/xml/BUILD.bazel +++ b/scripts/src/java/org/oppia/android/scripts/xml/BUILD.bazel @@ -52,3 +52,14 @@ kt_jvm_library( "//scripts/src/java/org/oppia/android/scripts/common:repository_file", ], ) + +kt_jvm_library( + name = "check_textview_styles", + testonly = True, + srcs = ["TextViewStyleCheck.kt"], + visibility = ["//scripts:oppia_script_binary_visibility"], + deps = [ + ":xml_syntax_error_handler", + "//scripts/src/java/org/oppia/android/scripts/common:repository_file", + ], +) diff --git a/scripts/src/java/org/oppia/android/scripts/xml/TextViewStyleCheck.kt b/scripts/src/java/org/oppia/android/scripts/xml/TextViewStyleCheck.kt new file mode 100644 index 00000000000..d17e2fa5c12 --- /dev/null +++ b/scripts/src/java/org/oppia/android/scripts/xml/TextViewStyleCheck.kt @@ -0,0 +1,62 @@ +package org.oppia.android.scripts.xml + +import java.io.File +import javax.xml.parsers.DocumentBuilderFactory + +/** + * Script to ensure all TextView elements in layout XML files use centrally managed styles. + * + * Usage: + * bazel run //scripts:check_textview_styles -- + * + * Arguments: + * - path_to_repository_root: The root path of the repository. + * + * Example: + * bazel run //scripts:check_textview_styles -- $(pwd) + */ +fun main(vararg args: String) { + require(args.isNotEmpty()) { + "Usage: bazel run" + + " //scripts:check_textview_styles -- " + } + + val repoRoot = File(args[0]) + require(repoRoot.exists()) { "Repository root path does not exist: ${args[0]}" } + + val resDir = File(repoRoot, "app/src/main/res") + require(resDir.exists()) { "Resource directory does not exist: ${resDir.path}" } + + val layoutDirs = resDir.listFiles { file -> file.isDirectory && file.name.startsWith("layout") } + ?: emptyArray() + val xmlFiles = layoutDirs.flatMap { dir -> + dir.walkTopDown().filter { file -> file.extension == "xml" }.toList() + } + + val builderFactory = DocumentBuilderFactory.newInstance() + val errors = mutableListOf() + + for (file in xmlFiles) { + val document = builderFactory.newDocumentBuilder().parse(file) + val textViewNodes = document.getElementsByTagName("TextView") + + for (i in 0 until textViewNodes.length) { + val node = textViewNodes.item(i) + val attributes = node.attributes + val styleAttribute = attributes?.getNamedItem("style")?.nodeValue + + if (styleAttribute == null || !styleAttribute.startsWith("@style/")) { + errors.add("${file.path}: TextView element is missing a centrally managed style.") + break + } + } + } + + if (errors.isNotEmpty()) { + println("TextView Style Check FAILED:") + errors.forEach { println(it) } + throw Exception("Some TextView elements do not have centrally managed styles.") + } else { + println("TextView Style Check PASSED.") + } +}