#!/usr/bin/env sh # epubcheck over the sample set, as a regression guard. # # Every epub spine writes is checked with epubcheck. A *fatal* is never # acceptable: it means a reader cannot parse the file at all. Errors are # compared against a recorded allowance, so that the ones known to be # outstanding do not fail the run while any new one does. # # The allowance is deliberately a single number rather than a list of # messages: a list invites adding to it. When the number goes down, lower it # here in the same commit that lowers it in the output. # # Usage: # SpinePOD=../../markup/sisudoc-spine-samples/markup/pod-samples/pod \ # ./test/test-epub-validity.sh ./bin/spine-ldc # # Exit codes: # 0 no fatals, and errors within the allowance # 1 a fatal, or more errors than allowed # 2 set-up problem (no $SpinePOD, no binary, no epubcheck, no samples) set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SPINE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" # What is known to be outstanding over the whole sample set. Both numbers are # a ceiling, so a regression fails and an improvement does not; lower them in # the commit that lowers the output, and say in that commit what went. # # There is no allowance for a fatal, and there must never be one. The last # one - the_public_domain, chapter_2: a bare url ending a footnote body # swallowed the "}~" close delimiter, so the note closed inside the link # markup and left an unbalanced behind - was a url boundary defect in # the abstraction, and is fixed. # # No error is allowed either, and none is outstanding. Both numbers being # zero is the point: anything at all that epubcheck calls an error is a # regression, and there is no list to add to. # # Two warnings remain and are not counted here. Both are NAV-011 in the # same shape, in two documents: the navigation document lists one file # twice, and the repeat is behind the previous entry in spine order. It # comes from how the endnotes part and section headings are ordered, not # from the navigation writer. FATALS_ALLOWED=${SpineEpubFatalsAllowed:-0} ERRORS_ALLOWED=${SpineEpubErrorsAllowed:-0} if [ -z "$SpinePOD" ]; then echo "ERROR: \$SpinePOD is not set." >&2 echo " e.g. SpinePOD=../../markup/sisudoc-spine-samples/markup/pod-samples/pod" >&2 exit 2 fi SAMPLES_RAW="$SPINE_DIR/$SpinePOD" if [ -d "$SAMPLES_RAW" ]; then SAMPLES_DIR="$(cd "$SAMPLES_RAW" && pwd)" else SAMPLES_DIR="$SAMPLES_RAW" fi # SPINE_BIN="${1:-}" # if [ -z "$SPINE_BIN" ] || [ ! -x "$SPINE_BIN" ]; then # echo "ERROR: give the spine binary, e.g. ./bin/spine-ldc" >&2 # exit 2 # fi SPINE_BIN="${1:-}" # find spine binary if [ -z "$SPINE_BIN" ]; then if [ -x "$SPINE_DIR/result/bin/spine" ]; then SPINE_BIN="$SPINE_DIR/result/bin/spine" elif [ -x "$SPINE_DIR/bin/spine-ldc" ]; then SPINE_BIN="$SPINE_DIR/bin/spine-ldc" elif [ -x "$SPINE_DIR/bin/spine" ]; then SPINE_BIN="$SPINE_DIR/bin/spine" else echo "ERROR: spine binary not found. Specify path as argument." >&2 exit 2 fi fi if [ ! -d "$SAMPLES_DIR" ]; then echo "ERROR: samples not found: $SAMPLES_DIR" >&2 exit 2 fi if ! command -v epubcheck >/dev/null 2>&1; then echo "ERROR: epubcheck not on PATH." >&2 echo " e.g. nix shell \"nixpkgs#epubcheck\" -c $0 $SPINE_BIN" >&2 exit 2 fi echo "spine binary: $SPINE_BIN" echo "samples: $SAMPLES_DIR" OUT_DIR="$(mktemp -d)" trap 'rm -rf "$OUT_DIR"' EXIT echo "Generating epubs ..." "$SPINE_BIN" --epub --output="$OUT_DIR" "$SAMPLES_DIR"/* 2>&1 | tail -1 FATALS=0 ERRORS=0 DOCS=0 for f in $(find "$OUT_DIR" -name '*.epub' | sort); do DOCS=$((DOCS + 1)) msg=$(epubcheck "$f" 2>&1 | grep -E '^Messages:' || true) ff=$(echo "$msg" | sed -n 's/.*: \([0-9]*\) fatal.*/\1/p') ee=$(echo "$msg" | sed -n 's/.*\/ \([0-9]*\) error.*/\1/p') ff=${ff:-0}; ee=${ee:-0} FATALS=$((FATALS + ff)) ERRORS=$((ERRORS + ee)) if [ "$ff" -gt 0 ]; then echo " FATAL in $(basename "$f"): $ff" epubcheck "$f" 2>&1 | grep -i 'FATAL' | head -3 | sed 's/^/ /' fi done echo "checked $DOCS epubs: $FATALS fatal (allowed $FATALS_ALLOWED), $ERRORS errors (allowed $ERRORS_ALLOWED)" if [ "$FATALS" -gt "$FATALS_ALLOWED" ]; then echo "FAIL: $FATALS fatal(s), more than the $FATALS_ALLOWED allowed;" echo " a fatal means a reader cannot parse that file at all" exit 1 fi if [ "$ERRORS" -gt "$ERRORS_ALLOWED" ]; then echo "FAIL: $ERRORS errors, more than the $ERRORS_ALLOWED allowed" echo " if this is a deliberate change, say why and adjust ERRORS_ALLOWED" exit 1 fi echo "PASS: $FATALS fatal and $ERRORS errors, both within what is recorded" exit 0