#!/bin/sh # yelp-check # Copyright (C) 2011 Shaun McCance # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. xsl_mal_link='@XSL_MAL_LINK@' xsl_mal_rng='@DATADIR@/xslt/mal-rng.xsl' urlencode () { # We usually don't want to urlencode slashes, because we're # usually converting file paths to URIs. But we do want to # urlencode slases for names of RNG files in validate_page. if [ "x$2" = "x/" ]; then urlencode_slash='' else urlencode_slash='\/' fi echo "$1" | LANG=C awk ' BEGIN { for (i = 1; i <= 255; i++) chars[sprintf("%c", i)] = i; } { ret = ""; for (i = 1; i <= length($0); i++) { c = substr($0, i, 1); if (c ~ /['$urlencode_slash'a-zA-Z0-9._-]/) ret = ret c; else ret = ret sprintf("%%%X%X", int(chars[c] / 16), chars[c] % 16); } print ret; }' } yelp_usage () { ( echo "Usage: yelp-check [OPTIONS] [FILES]" echo "" echo "Commands:" echo " orphans Find orphaned pages in a Mallard document" echo " links Find broken xref links in a Mallard document" echo " validate Validate files against a DTD or RNG" ) 1>&2 } yelp_usage_links () { ( echo "Usage: yelp-check links " echo "" echo " Find broken xref links in in a Mallard document." echo "" echo "Options:" echo " -c CACHE Use the existing Mallard cache CACHE" ) 1>&2 } yelp_usage_orphans () { ( echo "Usage: yelp-check orphans " echo "" echo " Locate orphaned pages among in a Mallard document." echo " Orphaned pages are any pages that cannot be reached by" echo " topic links alone from the index page." echo "" echo "Options:" echo " -c CACHE Use the existing Mallard cache CACHE" ) 1>&2 } yelp_usage_validate () { ( echo "Usage: yelp-check validate " echo "" echo " Validate FILES against the appropriate DTD or RNG." echo " For Mallard pages, perform automatic RNG merging" echo " based on the version attribute." ) 1>&2 } if [ $# = 0 ]; then yelp_usage exit 1 fi yelp_links_page () { ( echo '' xsl='file://'`urlencode "$xsl_mal_link"` echo '' check_cache_url='file://'`urlencode "$check_cache_file"` echo '' echo '' echo '' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' : ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo '' echo '' ) | xsltproc --xinclude - "$1" } yelp_links () { if [ "$#" = "0" -o "x$1" = "x--help" ]; then yelp_usage_links exit 1 fi while [ "$#" != "0" ]; do case "$1" in "-c") shift check_cache_file="$1" shift ;; *) break ;; esac done if [ "x$check_cache_file" != "x" ]; then check_cache_file=`(cd $(dirname "$check_cache_file") && pwd)`/`basename "$check_cache_file"` else check_cache_file_is_tmp="yes" check_cache_file=`mktemp` yelp-build cache -o "$check_cache_file" "$@" fi check_out_file=`mktemp` for xml in "$@"; do if [ -d "$xml" ]; then for page in "$xml"/*.page; do yelp_links_page "$page" done else yelp_links_page "$xml" fi done > "$check_out_file" ret=`cat "$check_out_file" | wc -l` if test "x$ret" != "x0"; then ret="1"; fi cat "$check_out_file" if [ "x$check_cache_file_is_tmp" = "xyes" ]; then rm "$check_cache_file" fi rm "$check_out_file" exit $ret } yelp_orphans_page () { ( echo '' xsl='file://'`urlencode "$xsl_mal_link"` echo '' check_cache_url='file://'`urlencode "$check_cache_file"` echo '' echo '' echo '' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo ' ' echo '' echo '' ) | xsltproc --xinclude - "$1" } yelp_orphans () { if [ "$#" = "0" -o "x$1" = "x--help" ]; then yelp_usage_orphans exit 1 fi while [ "$#" != "0" ]; do case "$1" in "-c") shift check_cache_file="$1" shift ;; *) break ;; esac done if [ "x$check_cache_file" != "x" ]; then check_cache_file=`(cd $(dirname "$check_cache_file") && pwd)`/`basename "$check_cache_file"` else check_cache_file_is_tmp="yes" check_cache_file=`mktemp` yelp-build cache -o "$check_cache_file" "$@" fi check_out_file=`mktemp` for xml in "$@"; do if [ -d "$xml" ]; then for page in "$xml"/*.page; do yelp_orphans_page "$page" done else yelp_orphans_page "$xml" fi done > "$check_out_file" ret=`cat "$check_out_file" | wc -l` if test "x$ret" != "x0"; then ret="1"; fi cat "$check_out_file" if [ "x$check_cache_file_is_tmp" = "xyes" ]; then rm "$check_cache_file" fi rm "$check_out_file" exit $ret } yelp_validate_page () { # Using temp files because pipes create subshells, making it really # hard to return the right exit status in a portable way. if [ "x$check_rng_dir" = "x" ]; then check_rng_dir=`mktemp -d` fi check_out_file=`mktemp` check_rng_file=`( echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '1.0' echo '' echo '' echo '' echo '' ) | xsltproc - "$1"` check_rng_file=`urlencode "$check_rng_file" /`.rng if [ ! -f "$check_rng_dir/$check_rng_file" ]; then # If we've already made an RNG file for this version string, don't # do it again. We've urlencoded the file name + slashes, because # version strings often contain slashes. But xsltproc treats the # -o option as a URL and urldecodes, so doubly urlencode, because # we want the urlencoded string to be the on-disk name. xsltproc -o "$check_rng_dir/"`urlencode "$check_rng_file"` "$xsl_mal_rng" "$1" fi xmllint --noout --xinclude --noent --relaxng "$check_rng_dir/$check_rng_file" "$1" > "$check_out_file" 2>&1 ret="$?" cat "$check_out_file" | grep -v 'validates$' rm "$check_out_file" return $ret; } yelp_validate () { if [ "$#" = "0" -o "x$1" = "x--help" ]; then yelp_usage_validate exit 1 fi gret="0" for xml in "$@"; do ext=`echo "$1" | sed -e 's/.*\.//'` if [ -d "$xml" ]; then for page in "$xml"/*.page; do yelp_validate_page "$page" || gret="$?" done elif [ "x$ext" = "xpage" ]; then yelp_validate_page "$xml" || gret="$?" else xmllint --noout --xinclude --noent --postvalid "$xml" || gret="$?" fi done if [ "x$check_rng_dir" != "x" ]; then rm "$check_rng_dir"/*.rng rmdir "$check_rng_dir" fi exit "$gret" } cmd="$1" shift case "x$cmd" in "xlinks") yelp_links "$@" ;; "xorphans") yelp_orphans "$@" ;; "xvalidate") yelp_validate "$@" ;; *) yelp_usage ;; esac