72 lines
2.8 KiB
PowerShell
72 lines
2.8 KiB
PowerShell
$ErrorActionPreference = 'Stop'
|
|
$root = Split-Path -Parent $PSScriptRoot
|
|
$coveragePath = Join-Path $PSScriptRoot 'responsive-layout-coverage.json'
|
|
$allowlistPath = Join-Path $PSScriptRoot 'responsive-layout-allowlist.json'
|
|
|
|
if (-not (Test-Path -LiteralPath $coveragePath)) { throw 'Missing responsive layout coverage owner' }
|
|
if (-not (Test-Path -LiteralPath $allowlistPath)) { throw 'Missing responsive layout allowlist owner' }
|
|
|
|
$coverage = Get-Content -LiteralPath $coveragePath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
$allowlist = Get-Content -LiteralPath $allowlistPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
$requiredFoundation = @(
|
|
'components/AppButton.vue',
|
|
'components/AppDialog.vue'
|
|
)
|
|
foreach ($required in $requiredFoundation) {
|
|
if ($coverage.covered -notcontains $required) {
|
|
throw "Responsive coverage cannot remove migrated foundation file: $required"
|
|
}
|
|
}
|
|
|
|
function Normalize-Selector([string]$selector) {
|
|
return (($selector -replace '\s+', ' ').Trim())
|
|
}
|
|
|
|
function Test-Allowlisted([string]$path, [string]$selector, [string]$property) {
|
|
$normalizedSelector = Normalize-Selector $selector
|
|
foreach ($entry in $allowlist.exceptions) {
|
|
if ($entry.path -eq $path -and
|
|
(Normalize-Selector $entry.selector) -eq $normalizedSelector -and
|
|
$entry.property -eq $property) {
|
|
return $true
|
|
}
|
|
}
|
|
return $false
|
|
}
|
|
|
|
$violations = [System.Collections.Generic.List[string]]::new()
|
|
foreach ($relativePath in $coverage.covered) {
|
|
$fullPath = Join-Path $root $relativePath
|
|
if (-not (Test-Path -LiteralPath $fullPath)) {
|
|
$violations.Add("missing covered file: $relativePath")
|
|
continue
|
|
}
|
|
|
|
$source = Get-Content -LiteralPath $fullPath -Raw -Encoding UTF8
|
|
$styleMatches = [regex]::Matches($source, '(?is)<style\b[^>]*>(?<css>.*?)</style>')
|
|
foreach ($styleMatch in $styleMatches) {
|
|
$css = $styleMatch.Groups['css'].Value
|
|
$ruleMatches = [regex]::Matches($css, '(?ms)(?<selector>[^{}]+)\{(?<body>[^{}]*)\}')
|
|
foreach ($rule in $ruleMatches) {
|
|
$selector = Normalize-Selector $rule.Groups['selector'].Value
|
|
$body = $rule.Groups['body'].Value
|
|
$checks = @(
|
|
@{ Name = 'fixed-height'; Pattern = '(?im)(?<![-\w])height\s*:\s*\d+(?:\.\d+)?rpx\b' },
|
|
@{ Name = 'background-stretch'; Pattern = '(?im)background\s*:[^;\r\n]*100%\s+100%[^;\r\n]*;' },
|
|
@{ Name = 'direct-border-image-slice'; Pattern = '(?im)border-image-slice\s*:' }
|
|
)
|
|
foreach ($check in $checks) {
|
|
if ($body -match $check.Pattern -and -not (Test-Allowlisted $relativePath $selector $check.Name)) {
|
|
$violations.Add("$relativePath :: $selector :: $($check.Name)")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($violations.Count -gt 0) {
|
|
throw ("Responsive layout contract violations:`n - " + ($violations -join "`n - "))
|
|
}
|
|
|
|
Write-Output 'PROJECT-RESPONSIVE-LAYOUT-CONTRACT PASS'
|