#!/bin/sh # script/prettier: run prettier over this repo's canonical file set. # # Takes exactly one mode argument, --write or --check, and applies the # same patterns in both modes. script/fmt and script/fmt-check both go # through here, so the set of files that get formatted and the set that # get verified cannot drift apart. # # Failures are never swallowed: a missing prettier is an error, not a # silent skip. A formatter that quietly does nothing is worse than one # that fails loudly. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" usage() { echo "usage: script/prettier --write|--check" >&2 exit 2 } # Only the prettier yarn installed from yarn.lock, never one on PATH: a # different version formats differently. PRETTIER="$ROOT/node_modules/.bin/prettier" main() { [ "$#" -eq 1 ] || usage case "$1" in --write | --check) mode="$1" ;; *) usage ;; esac cd "$ROOT" # node_modules keeps the old prettier after package.json moves to a new # one, until script/bootstrap runs again, so compare the two. A prettier # that runs also means node is on PATH, which reading package.json needs. if ! installed="$("$PRETTIER" --version 2>/dev/null)"; then echo "prettier: not installed; run script/bootstrap" >&2 exit 1 fi pinned="$(node -p 'require("./package.json").devDependencies.prettier')" if [ "$installed" != "$pinned" ]; then echo "prettier: package.json pins $pinned but $installed is" \ "installed; run script/bootstrap" >&2 exit 1 fi # Markdown and JSON, repo-wide rather than root-only, so files in # subdirectories (docs/, once it exists) are covered too. Exclusions # live in .prettierignore; REPO_POLICIES.md is excluded there because # it is a verbatim copy of an upstream document. # # --no-error-on-unmatched-pattern is deliberately NOT used: both # patterns always match at least one tracked file (README.md, # package.json), so an empty match means the glob broke, and prettier # erroring out is exactly what we want rather than a vacuous pass. "$PRETTIER" "$mode" "**/*.md" "$PRETTIER" "$mode" "**/*.json" } main "$@"