All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
75 lines
2.1 KiB
Bash
75 lines
2.1 KiB
Bash
#!/usr/bin/env bash
|
|
# audit-css-collisions.sh — Find duplicate class selectors across kernel CSS files
|
|
# Outputs a JSON collision report to stdout.
|
|
# Usage: bash scripts/audit-css-collisions.sh [css-dir]
|
|
|
|
set -euo pipefail
|
|
CSS_DIR="${1:-src/css}"
|
|
|
|
# Extract class selectors from CSS files and track their file + line
|
|
declare -A SEEN # selector -> "file:line file:line ..."
|
|
|
|
for f in "$CSS_DIR"/*.css; do
|
|
[ -f "$f" ] || continue
|
|
lineno=0
|
|
while IFS= read -r line; do
|
|
lineno=$((lineno + 1))
|
|
# Extract class selectors (e.g. .foo-bar, .foo__bar--baz)
|
|
# Skip lines that are comments, inside @keyframes, or @media queries
|
|
[[ "$line" =~ ^[[:space:]]*/\* ]] && continue
|
|
[[ "$line" =~ ^[[:space:]]*@keyframes ]] && continue
|
|
|
|
# Match class selectors at the start of a rule
|
|
while [[ "$line" =~ \.([a-zA-Z_][a-zA-Z0-9_-]*) ]]; do
|
|
cls=".${BASH_REMATCH[1]}"
|
|
entry="$(basename "$f"):$lineno"
|
|
if [ -n "${SEEN[$cls]:-}" ]; then
|
|
SEEN[$cls]="${SEEN[$cls]} $entry"
|
|
else
|
|
SEEN[$cls]="$entry"
|
|
fi
|
|
# Remove the matched portion to find more classes on the same line
|
|
line="${line#*${BASH_REMATCH[0]}}"
|
|
done
|
|
done < "$f"
|
|
done
|
|
|
|
# Build JSON: only emit selectors defined in more than one file
|
|
echo "["
|
|
first=true
|
|
for cls in "${!SEEN[@]}"; do
|
|
locations="${SEEN[$cls]}"
|
|
# Get unique files
|
|
files=()
|
|
for loc in $locations; do
|
|
file="${loc%%:*}"
|
|
found=false
|
|
for f in "${files[@]:-}"; do
|
|
[ "$f" = "$file" ] && found=true && break
|
|
done
|
|
$found || files+=("$file")
|
|
done
|
|
|
|
# Only report if defined in 2+ different files
|
|
[ ${#files[@]} -lt 2 ] && continue
|
|
|
|
if $first; then first=false; else echo ","; fi
|
|
|
|
# Build locations array
|
|
locs_json=""
|
|
for loc in $locations; do
|
|
[ -n "$locs_json" ] && locs_json="$locs_json, "
|
|
locs_json="$locs_json\"$loc\""
|
|
done
|
|
|
|
files_json=""
|
|
for f in "${files[@]}"; do
|
|
[ -n "$files_json" ] && files_json="$files_json, "
|
|
files_json="$files_json\"$f\""
|
|
done
|
|
|
|
printf ' {"selector": "%s", "files": [%s], "locations": [%s]}' "$cls" "$files_json" "$locs_json"
|
|
done
|
|
echo ""
|
|
echo "]"
|