#!/usr/bin/env bash # theme.css overrides a vendor stylesheet it does not control, and the way that # goes wrong is silent: the rule is there, the page still looks like Suramadu. # # It went wrong exactly once already. Upstream paints the modal twice, at two # different depths, and styles every link pseudo-class - so a two-class override # and a bare `a` both lost, and the dialog stayed white with an orange link. # # The convention that fixes it is a :root prefix on every rule, which outranks # anything in style.css without !important. This checks the convention holds. set -uo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" CSS="$ROOT/suramadu/web/theme.css" pass=0; fail=0 check() { if "${@:2}"; then echo "ok $1"; pass=$((pass+1)); else echo "FAIL $1"; fail=$((fail+1)); fi; } [ -f "$CSS" ] || { echo "FAIL theme.css is missing"; exit 1; } # Selector lines are the ones ending in { or , outside a declaration block. # Comments and declarations are skipped; :root {...} itself is the one rule # allowed to stand alone, since it only declares custom properties. # # At-rule preludes are skipped too. `@media ... {` ends in a brace and would # read as a bare selector, but it is not one: it opens a block whose selectors # are checked on their own lines, and nothing about it can lose a specificity # fight. The rule the check exists for is unchanged - every selector, including # the ones nested inside an at-rule, still has to start with :root. mapfile -t bare < <( awk ' /\/\*/ { inc = 1 } inc { if (/\*\//) inc = 0; next } /^[[:space:]]*$/ { next } /^[[:space:]]*@/ { next } /^[[:space:]]*:root[[:space:]]*\{/ { next } /[{,][[:space:]]*$/ { line = $0 sub(/^[[:space:]]+/, "", line) if (line !~ /^:root/) print line } ' "$CSS" ) check "every selector is prefixed with :root" test "${#bare[@]}" -eq 0 if [ "${#bare[@]}" -ne 0 ]; then printf ' %s\n' "${bare[@]}" echo " Without it the rule loses to style.css and silently does nothing." fi # The two upstream patterns that beat the first attempt. check "the deeper .suramadu-element-content modal scoping is covered" \ grep -q '\.suramadu-element \.suramadu-element-content \.ws-modal' "$CSS" check "link pseudo-classes are covered, not just a bare a" \ grep -q 'a:link' "$CSS" # No !important: if a rule needs it, the selector is wrong. Comments are # stripped first - this file's own commentary mentions the word. NOCOMMENT="$(mktemp)" trap 'rm -f "$NOCOMMENT"' EXIT awk '/\/\*/ { inc = 1 } inc { if (/\*\//) inc = 0; next } { print }' "$CSS" > "$NOCOMMENT" check "no !important in any declaration" bash -c "! grep -q '!important' '$NOCOMMENT'" echo echo "$pass passed, $fail failed" [ "$fail" -eq 0 ]