88 lines
4.4 KiB
PowerShell
88 lines
4.4 KiB
PowerShell
$ErrorActionPreference = 'Stop'
|
|
Add-Type -AssemblyName System.Drawing
|
|
|
|
$root = Split-Path -Parent $PSScriptRoot
|
|
$componentsRoot = Join-Path $root 'components'
|
|
$pagesRoot = Join-Path $root 'pages'
|
|
|
|
function Read-Utf8([string]$Path) {
|
|
return Get-Content -Raw -Encoding UTF8 $Path
|
|
}
|
|
|
|
foreach ($component in @('AppButton.vue', 'AppDialog.vue', 'AppToast.vue', 'AppLoading.vue', 'ModulePageBackground.vue')) {
|
|
$path = Join-Path $componentsRoot $component
|
|
if (-not (Test-Path -LiteralPath $path)) { throw "Missing global visual component: $component" }
|
|
}
|
|
|
|
$button = Read-Utf8 (Join-Path $componentsRoot 'AppButton.vue')
|
|
$profiles = Read-Utf8 (Join-Path $root 'styles/adaptive-frame-profiles.scss')
|
|
if ($button -notmatch 'adaptive-scroll-button' -or $profiles -notmatch 'a01-scroll-primary-v3\.png') { throw 'AppButton does not consume the approved A-series primary scroll profile.' }
|
|
if ($button -notmatch 'adaptive-scroll-button' -or $profiles -notmatch 'a01-scroll-secondary-v3\.png') { throw 'AppButton does not consume the approved A-series secondary scroll profile.' }
|
|
|
|
$dialog = Read-Utf8 (Join-Path $componentsRoot 'AppDialog.vue')
|
|
if ($dialog -notmatch 'adaptive-auth-dialog' -or $profiles -notmatch 'a01-scroll-dialog-v3\.png') { throw 'AppDialog does not consume the approved A-series dialog profile.' }
|
|
|
|
$toast = Read-Utf8 (Join-Path $componentsRoot 'AppToast.vue')
|
|
if ($toast -notmatch 'adaptive-feedback-toast' -or $profiles -notmatch 'a01-scroll-toast-v3\.png') { throw 'AppToast does not consume the approved A-series toast profile.' }
|
|
|
|
$header = Read-Utf8 (Join-Path $componentsRoot 'PageHeader.vue')
|
|
if ($header -notmatch 'chevron-right\.png') { throw 'PageHeader does not use the approved image arrow.' }
|
|
if ($header -match '\{\{\s*backLabel\s*\}\}') { throw 'PageHeader still renders a text back label.' }
|
|
if ($header -notmatch 'scaleX\(-1\)') { throw 'PageHeader back arrow is not oriented toward the previous page.' }
|
|
|
|
$activeSources = @(
|
|
Get-ChildItem -LiteralPath $componentsRoot -Recurse -File -Filter '*.vue'
|
|
Get-ChildItem -LiteralPath $pagesRoot -Recurse -File -Filter '*.vue' | Where-Object { $_.Name -ne 'a06-auth-status.vue' }
|
|
)
|
|
foreach ($source in $activeSources) {
|
|
$content = Read-Utf8 $source.FullName
|
|
foreach ($forbidden in @(
|
|
'uni.showToast',
|
|
'uni.showModal',
|
|
'uni.showLoading',
|
|
'uni.showActionSheet',
|
|
'/static/assets/foundation/opaque/a01-primary-button.png',
|
|
'/static/assets/foundation/opaque/a01-secondary-button.png'
|
|
)) {
|
|
if ($content.Contains($forbidden)) { throw "$($source.FullName) still contains forbidden global UI path: $forbidden" }
|
|
}
|
|
}
|
|
|
|
$background = Read-Utf8 (Join-Path $componentsRoot 'ModulePageBackground.vue')
|
|
$moduleAssets = @{
|
|
tree = 'tree-page-background-long.png'
|
|
family = 'family-page-background-long.png'
|
|
records = 'records-page-background-long.png'
|
|
notification = 'notification-page-background-long.png'
|
|
profile = 'profile-page-background-long.png'
|
|
}
|
|
foreach ($entry in $moduleAssets.GetEnumerator()) {
|
|
if ($background -notmatch [regex]::Escape($entry.Value)) { throw "ModulePageBackground is missing $($entry.Key) mapping." }
|
|
$asset = Get-ChildItem -LiteralPath (Join-Path $root 'static/assets/modules') -Recurse -File -Filter $entry.Value
|
|
if (-not $asset) { throw "Missing module background asset: $($entry.Value)" }
|
|
$image = [System.Drawing.Image]::FromFile($asset.FullName)
|
|
try {
|
|
if ($image.Width -ne 1440 -or $image.Height -ne 3600) {
|
|
throw "$($entry.Value) must be 1440x3600, got $($image.Width)x$($image.Height)."
|
|
}
|
|
}
|
|
finally {
|
|
$image.Dispose()
|
|
}
|
|
}
|
|
|
|
$modulePage = Read-Utf8 (Join-Path $componentsRoot 'ModulePage.vue')
|
|
foreach ($token in @('<ModulePageBackground', '<AppButton', '<AppToast')) {
|
|
if ($modulePage -notmatch [regex]::Escape($token)) { throw "ModulePage does not consume $token." }
|
|
}
|
|
|
|
$g01 = Read-Utf8 (Join-Path $pagesRoot 'genealogy/g01-my-genealogies.vue')
|
|
if ($g01 -notmatch '(?s)\.current-meta\s*\{[^}]*color:\s*#62584c;[^}]*font-weight:\s*500;') { throw 'G01 current genealogy metadata is not using the approved readable style.' }
|
|
|
|
$genealogyCard = Read-Utf8 (Join-Path $componentsRoot 'GenealogyCard.vue')
|
|
foreach ($selector in @('card-meta', 'card-updated', 'card-role')) {
|
|
if ($genealogyCard -notmatch "(?s)\.$selector\s*\{[^}]*color:\s*#62584c;[^}]*font-weight:\s*500;") { throw "GenealogyCard $selector is not using the approved readable style." }
|
|
}
|
|
|
|
Write-Output 'PASS global heritage visual system contract'
|