134 lines
3.7 KiB
PowerShell
134 lines
3.7 KiB
PowerShell
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 |