$ErrorActionPreference = "Stop"
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
$layoutRoot = Join-Path $repoRoot "app/src/main/res/layout"
$valuesRoot = Join-Path $repoRoot "app/src/main/res/values"
$themesPath = Join-Path $valuesRoot "themes.xml"
$failures = New-Object System.Collections.Generic.List[string]
function Add-Failure([string] $message) {
$failures.Add($message) | Out-Null
}
function Get-XmlLine([string] $content, [int] $index) {
if ($index -lt 0) {
return 1
}
return (($content.Substring(0, $index) -split "`n").Count)
}
function Get-AttributeValue([string] $block, [string] $attributeName) {
$escapedName = [regex]::Escape($attributeName)
$match = [regex]::Match($block, "$escapedName=""([^""]+)""")
if ($match.Success) {
return $match.Groups[1].Value
}
return $null
}
function Assert-MinDp([string] $value, [int] $minimum, [string] $where, [string] $attributeName) {
if ([string]::IsNullOrWhiteSpace($value)) {
Add-Failure "$where is missing $attributeName"
return
}
if ($value -notmatch "^([0-9]+)dp$") {
Add-Failure "$where has non-fixed $attributeName='$value'"
return
}
$actual = [int] $Matches[1]
if ($actual -lt $minimum) {
Add-Failure "$where has $attributeName=${actual}dp, expected at least ${minimum}dp"
}
}
$xmlFiles = Get-ChildItem -Path @($layoutRoot, $valuesRoot) -Filter "*.xml" -Recurse
foreach ($file in $xmlFiles) {
$content = Get-Content $file.FullName -Raw -Encoding UTF8
$relativePath = Resolve-Path -Relative $file.FullName
$textSizeDpMatches = [regex]::Matches($content, 'android:textSize="[0-9.]+dp"')
foreach ($match in $textSizeDpMatches) {
$line = Get-XmlLine $content $match.Index
Add-Failure "${relativePath}:$line uses dp for textSize; use sp"
}
$materialButtons = [regex]::Matches($content, '(?s)')
foreach ($match in $materialButtons) {
$line = Get-XmlLine $content $match.Index
$where = "${relativePath}:$line MaterialButton"
$block = $match.Value
if ($block -match 'android:minWidth="0dp"') {
Add-Failure "$where resets minWidth to 0dp"
}
$minHeight = Get-AttributeValue $block "android:minHeight"
if (-not [string]::IsNullOrWhiteSpace($minHeight)) {
Assert-MinDp $minHeight 48 $where "android:minHeight"
}
}
$imageButtons = [regex]::Matches($content, '(?s)')
foreach ($match in $imageButtons) {
$line = Get-XmlLine $content $match.Index
$where = "${relativePath}:$line ImageButton"
$block = $match.Value
Assert-MinDp (Get-AttributeValue $block "android:layout_width") 48 $where "android:layout_width"
Assert-MinDp (Get-AttributeValue $block "android:layout_height") 48 $where "android:layout_height"
}
}
$themesContent = Get-Content $themesPath -Raw -Encoding UTF8
foreach ($styleName in @("Primary", "Secondary", "Tonal")) {
$stylePattern = "(?s)