forked from fa/breadcrumb-the-shire
96 lines
2.7 KiB
Bash
Executable File
96 lines
2.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
repo_root="$(cd -- "${script_dir}/.." && pwd)"
|
|
cd "${repo_root}"
|
|
|
|
if ! command -v rg >/dev/null 2>&1; then
|
|
echo "[ERROR] rg is required for css-contract-check." >&2
|
|
exit 2
|
|
fi
|
|
|
|
failures=0
|
|
|
|
ok() {
|
|
echo "[OK] $*"
|
|
}
|
|
|
|
fail() {
|
|
echo "[FAIL] $*" >&2
|
|
failures=$((failures + 1))
|
|
}
|
|
|
|
expected_layer_order='@layer tokens, vendor, layout, vendor-overrides, components, pages, utilities;'
|
|
if rg -Fq "${expected_layer_order}" web/css/app-layers.css; then
|
|
ok "Layer order declaration found in web/css/app-layers.css"
|
|
else
|
|
fail "Layer order declaration is missing or changed in web/css/app-layers.css"
|
|
fi
|
|
|
|
while IFS= read -r file; do
|
|
expected_layer=''
|
|
case "${file}" in
|
|
web/css/base/*|modules/*/web/css/base/*)
|
|
expected_layer='tokens'
|
|
;;
|
|
web/css/layout/*|modules/*/web/css/layout/*)
|
|
expected_layer='layout'
|
|
;;
|
|
web/css/components/*|modules/*/web/css/components/*)
|
|
expected_layer='components'
|
|
;;
|
|
web/css/pages/*|modules/*/web/css/pages/*)
|
|
expected_layer='pages'
|
|
;;
|
|
web/css/vendor-overrides/*|modules/*/web/css/vendor-overrides/*)
|
|
expected_layer='vendor-overrides'
|
|
;;
|
|
esac
|
|
|
|
if [[ -z "${expected_layer}" ]]; then
|
|
continue
|
|
fi
|
|
|
|
if [[ "${file}" == "web/css/pages/app-error.css" || "${file}" == "web/css/pages/app-error-debug.css" ]]; then
|
|
continue
|
|
fi
|
|
|
|
detected_layer="$(sed -n '1,120p' "${file}" | sed -nE 's/.*@layer[[:space:]]+([^[:space:]{]+).*/\1/p' | head -n1)"
|
|
if [[ -z "${detected_layer}" ]]; then
|
|
fail "${file}: missing @layer declaration near file top"
|
|
continue
|
|
fi
|
|
|
|
if [[ "${detected_layer}" != "${expected_layer}" ]]; then
|
|
fail "${file}: @layer ${detected_layer} does not match expected ${expected_layer}"
|
|
fi
|
|
done < <(rg --files web/css modules | rg '\.css$')
|
|
|
|
remote_import_pattern='@import[[:space:]]+url\(["'"'"']?(https?:)?//|@import[[:space:]]+["'"'"']?(https?:)?//'
|
|
remote_hits="$(rg -n -g '*.css' -e "${remote_import_pattern}" web/css modules || true)"
|
|
if [[ -n "${remote_hits}" ]]; then
|
|
fail "Remote CSS import detected (must vendor locally):"
|
|
echo "${remote_hits}" >&2
|
|
else
|
|
ok "No remote CSS imports detected"
|
|
fi
|
|
|
|
if [[ ! -f web/css/core.css ]]; then
|
|
fail "web/css/core.css is missing"
|
|
else
|
|
first_import="$(rg -n '^@import' web/css/core.css | head -n1 || true)"
|
|
if [[ "${first_import}" == *'app-layers.css'* ]]; then
|
|
ok "web/css/core.css imports app-layers.css first"
|
|
else
|
|
fail "web/css/core.css must import app-layers.css as first @import"
|
|
fi
|
|
fi
|
|
|
|
if [[ "${failures}" -gt 0 ]]; then
|
|
echo "[FAIL] CSS contract check failed with ${failures} issue(s)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "[OK] CSS contract check passed."
|