69 lines
3.1 KiB
PowerShell
69 lines
3.1 KiB
PowerShell
$ErrorActionPreference = 'Stop'
|
|
|
|
$root = Split-Path -Parent $PSScriptRoot
|
|
$componentPath = Join-Path $root 'components/ModulePage.vue'
|
|
if (-not (Test-Path -LiteralPath $componentPath)) { throw 'Missing shared module page component' }
|
|
$component = Get-Content -LiteralPath $componentPath -Raw -Encoding utf8
|
|
|
|
foreach ($anchor in @(
|
|
'const moduleState = ref(',
|
|
'["loading", "empty", "success", "error"].includes(query.state)',
|
|
'module-state--${moduleState}',
|
|
'empty: {',
|
|
'success: {',
|
|
'error: {',
|
|
'module-content-frame.png',
|
|
'module-field-frame.png',
|
|
'<AppLoading',
|
|
'<AppButton',
|
|
'<AppToast',
|
|
'<ModulePageBackground',
|
|
':style="moduleAssetStyle"',
|
|
'@use "../styles/adaptive-frame-profiles.scss" as adaptive;',
|
|
'@include adaptive.adaptive-module-field;',
|
|
'@include adaptive.adaptive-module-content;',
|
|
'const moduleAssetStyle = computed(() => ({',
|
|
'"--module-content-asset": `url(${contentAsset.value})`',
|
|
'"--module-field-asset": `url(${fieldAsset.value})`',
|
|
'query.state'
|
|
)) {
|
|
if ($component -notmatch [regex]::Escape($anchor)) { throw "ModulePage is missing high-spec anchor: $anchor" }
|
|
}
|
|
|
|
foreach ($forbidden in @(
|
|
'class="page-intro"',
|
|
'g03-create-flow-panel.png',
|
|
'g06-search-input-wide.png',
|
|
'application-status-card.png',
|
|
'background: var(--module-field-asset) center / 100% 100% no-repeat;',
|
|
'background: var(--module-content-asset) center / 100% 100% no-repeat;',
|
|
'height: 100%;'
|
|
)) {
|
|
if ($component -match [regex]::Escape($forbidden)) { throw "ModulePage must not keep obsolete shared surface: $forbidden" }
|
|
}
|
|
|
|
foreach ($className in @('module-panel', 'form-row', 'list-card', 'detail-card', 'timeline-row', 'settings-row', 'status-card')) {
|
|
foreach ($property in @('border', 'border-radius', 'box-shadow')) {
|
|
if ($component -match "(?s)\.$className\s*\{[^}]*\b$property\s*:") {
|
|
throw "ModulePage must not construct .$className with CSS $property"
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($component -match '::before|::after') { throw 'ModulePage must not draw visible decorations with CSS pseudo-elements' }
|
|
if ($component -match '<image\b') { throw 'ModulePage must use approved container backgrounds instead of decorative image layers' }
|
|
if ($component -match '(?im)(?<![-\w])position\s*:') { throw 'ModulePage ordinary content must not use position declarations' }
|
|
|
|
foreach ($rule in @(
|
|
'(?s)\.module-page\s*\{[^}]*display:\s*flex;[^}]*flex-direction:\s*column;',
|
|
'(?s)\.module-page__header,\s*\.module-page__content,\s*\.module-page__loading\s*\{[^}]*z-index:\s*1;',
|
|
'(?s)\.module-lead\s*\{[^}]*background:\s*url\("/static/assets/modules/genealogy/transparent/section-divider\.png"\) center / 100% 100% no-repeat;',
|
|
'(?s)\.module-lead\s*\{[^}]*display:\s*flex;[^}]*align-items:\s*center;[^}]*justify-content:\s*center;',
|
|
'(?s)\.form-row,\s*\.settings-row\s*\{[^}]*@include\s+adaptive\.adaptive-module-field;',
|
|
'(?s)\.list-card,\s*\.detail-card,\s*\.timeline-row,\s*\.status-card\s*\{[^}]*@include\s+adaptive\.adaptive-module-content;'
|
|
)) {
|
|
if ($component -notmatch $rule) { throw "ModulePage document-flow background rule missing: $rule" }
|
|
}
|
|
|
|
Write-Output 'MODULE-PAGE-VISUAL-CONTRACT PASS'
|