param ( [Parameter(Mandatory = $true)] [string]$RootPath, [string]$NpxSassPackage = "sass@1.77.8", [bool]$NoErrorCss = $true ) $ErrorActionPreference = 'Stop' try { $resolvedRoot = (Resolve-Path -Path $RootPath).Path } catch { Write-Host "ERROR: Root path not found: $RootPath" -ForegroundColor Red exit 2 } Write-Host "Scanning SCSS files in: $resolvedRoot" -ForegroundColor Cyan function Get-SassRunner { param( [Parameter(Mandatory = $true)] [string]$StartPath, [Parameter(Mandatory = $true)] [string]$PinnedNpxPackage ) $current = $StartPath while ($true) { $localSass = Join-Path $current "node_modules\\.bin\\sass.cmd" if (Test-Path $localSass) { return @{ Command = $localSass PrefixArgs = @() Source = "local" } } $parent = Split-Path -Path $current -Parent if (-not $parent -or $parent -eq $current) { break } $current = $parent } $npxCmd = Get-Command npx.cmd -ErrorAction SilentlyContinue if ($npxCmd) { cmd /d /c "npx -y -p $PinnedNpxPackage sass --version >nul 2>&1" | Out-Null if ($LASTEXITCODE -eq 0) { return @{ Command = $npxCmd.Source PrefixArgs = @("-y", "-p", $PinnedNpxPackage, "sass") Source = "npx:$PinnedNpxPackage" } } } $sassCmd = Get-Command sass.cmd -ErrorAction SilentlyContinue if ($sassCmd) { cmd /d /c "sass --version >nul 2>&1" | Out-Null if ($LASTEXITCODE -eq 0) { return @{ Command = $sassCmd.Source PrefixArgs = @() Source = "global" } } } return $null } $sassRunner = Get-SassRunner -StartPath $resolvedRoot -PinnedNpxPackage $NpxSassPackage if (-not $sassRunner) { Write-Host "ERROR: No working Sass runner found (local sass.cmd, global sass, or npx sass)." -ForegroundColor Red exit 3 } Write-Host "Using Sass runner: $($sassRunner.Source) [$($sassRunner.Command)]" -ForegroundColor DarkCyan # Find all SCSS files recursively from the given root path. $files = Get-ChildItem -Path $resolvedRoot -Recurse -File -Filter "*.scss" if ($files.Count -eq 0) { Write-Host "No SCSS files found." -ForegroundColor Yellow exit 0 } $hasErrors = $false $checkedCount = 0 $errorCount = 0 foreach ($file in $files) { $checkedCount += 1 Write-Host "Checking: $($file.FullName)" -ForegroundColor Gray # Syntax-only validation: compile to NUL to avoid creating/opening any CSS files. $sassArgs = @($sassRunner.PrefixArgs) + @('--no-source-map', '--style=compressed', '--quiet', "--load-path=$resolvedRoot") if ($NoErrorCss) { $sassArgs += '--no-error-css' } $sassArgs += @($file.FullName, 'NUL') $previousErrorAction = $ErrorActionPreference $ErrorActionPreference = 'Continue' try { $result = & $sassRunner.Command @sassArgs 2>&1 | Out-String $exitCode = $LASTEXITCODE } finally { $ErrorActionPreference = $previousErrorAction } if ($exitCode -ne 0) { $hasErrors = $true $errorCount += 1 Write-Host "" Write-Host "ERROR in $($file.FullName)" -ForegroundColor Red Write-Host $result -ForegroundColor Yellow Write-Host "----------------------------------------" } } Write-Host "" Write-Host "Checked files: $checkedCount" if (-not $hasErrors) { Write-Host "All SCSS files are syntactically valid." -ForegroundColor Green exit 0 } Write-Host "SCSS files with errors: $errorCount" -ForegroundColor Red exit 1