[mallard-site-tool] Adding "media" command to copy media into outdir
[projectmallard:mallard-site-tool.git] / mallard-site-tool.in
1 #!/bin/sh
2 # -*- indent-tabs-mode: nil -*-
3 # mallard-site-tool  Build web sites from collections of Mallard documents
4 # Copyright (C) 2006-2010 Shaun McCance <shaunm@gnome.org>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 progname=`echo "$0" | sed 's%^.*/%%'`
21
22 PROGRAM=mallard-site-tool
23 VERSION=@VERSION@
24 prefix=@prefix@
25 datarootdir=@datarootdir@
26 datadir=@datadir@
27
28 # This is important to make sure string manipulation is handled
29 # byte-by-byte.
30 export LANG=C
31
32 XSL_CACHE='
33 <xsl:stylesheet
34   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
35   xmlns:cache="http://projectmallard.org/cache/1.0/"
36   xmlns:site="http://projectmallard.org/site/1.0/"
37   xmlns:mal="http://projectmallard.org/1.0/"
38   version="1.0">
39 <xsl:import href="'$(pkg-config --variable xsltdir yelp-xsl)'/mallard/cache/mal-cache.xsl"/>
40 <xsl:template name="mal.cache.id">
41   <xsl:param name="node" select="."/>
42   <xsl:param name="node_in"/>
43   <xsl:choose>
44     <xsl:when test="not($node/@id)"/>
45     <xsl:when test="$node/self::mal:page">
46       <xsl:attribute name="id">
47         <xsl:value-of select="$node_in/@site:dir"/>
48         <xsl:value-of select="$node/@id"/>
49       </xsl:attribute>
50     </xsl:when>
51     <xsl:otherwise>
52       <xsl:attribute name="id">
53         <xsl:value-of select="$node_in/@site:dir"/>
54         <xsl:value-of select="ancestor::mal:page[1]/@id"/>
55         <xsl:text>#</xsl:text>
56         <xsl:value-of select="@id"/>
57       </xsl:attribute>
58     </xsl:otherwise>
59   </xsl:choose>
60   <xsl:copy-of select="$node_in/@site:dir"/>
61 </xsl:template>
62 <xsl:template name="mal.cache.xref">
63   <xsl:param name="node" select="."/>
64   <xsl:param name="node_in"/>
65   <xsl:attribute name="xref">
66     <xsl:choose>
67       <xsl:when test="starts-with($node/@xref, '\''/'\'')">
68         <xsl:value-of select="$node/@xref"/>
69       </xsl:when>
70       <xsl:when test="starts-with($node/@xref, '\''#'\'')">
71         <xsl:value-of select="$node/@xref"/>
72       </xsl:when>
73       <xsl:otherwise>
74         <xsl:value-of select="$node_in/@site:dir"/>
75         <xsl:value-of select="$node/@xref"/>
76       </xsl:otherwise>
77     </xsl:choose>
78   </xsl:attribute>
79 </xsl:template>
80 </xsl:stylesheet>'
81
82 XSL_MALLARD_MEDIA='
83 <xsl:stylesheet
84   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
85   xmlns:mal="http://projectmallard.org/1.0/"
86   version="1.0">
87 <xsl:output method="text" encoding="utf-8"/>
88 <xsl:template match="/">
89   <xsl:for-each select="//mal:media">
90     <xsl:value-of select="@src"/>
91     <xsl:text>&#x000A;</xsl:text>
92   </xsl:for-each>
93 </xsl:template>
94 </xsl:stylesheet>'
95
96 XSL_GET_ROOT='
97 <xsl:stylesheet
98   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
99   xmlns:site="http://projectmallard.org/site/1.0/"
100   version="1.0">
101 <xsl:output method="text" encoding="utf-8"/>
102 <xsl:template match="/site:site">
103 <xsl:value-of select="site:link[@type='\'site-root\'']/@href"/>
104 </xsl:template>
105 </xsl:stylesheet>'
106
107 XSL_GET_CUSTOM='
108 <xsl:stylesheet
109   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
110   xmlns:site="http://projectmallard.org/site/1.0/"
111   version="1.0">
112 <xsl:output method="text" encoding="utf-8"/>
113 <xsl:template match="/site:site">
114 <xsl:value-of select="site:link[@type='\'site-custom-xsl\'']/@href"/>
115 </xsl:template>
116 </xsl:stylesheet>'
117
118 error() {
119     echo "$progname: $1" 1>&2;
120     exit 1;
121 }
122
123 print_help() {
124     cat <<EOF
125 Usage: $progname <COMMAND> [OPTIONS] FILES...
126 Process a Mallard site.
127
128 COMMAND is one of:
129   cache        generate a Mallard site cache file
130   css          generate the index.css file
131   media        copy media to the output directory
132   html         convert the site to HTML
133   help         display this help and exit
134 EOF
135 }
136
137 print_help_html() {
138     format="$1"
139     upformat=`echo $format | tr a-z A-Z`
140     cat <<EOF
141 Usage: $progname $format [OPTIONS] FILE
142 Convert FILE into $upformat.
143
144   -o, --output=DIR                the output directory
145   -s, --site=SITE                 base name of the site file
146 EOF
147 }
148
149 print_help_cache() {
150     cat <<EOF
151 Usage: $progname cache [OPTIONS]
152 Create a Mallard site cache file.
153
154   -s, --site=SITE                 base name of the site file
155 EOF
156 }
157
158 print_help_css() {
159     cat <<EOF
160 Usage: $progname css [OPTIONS]
161 Create the index.css file for a site.
162
163   -o, --output=DIR                the output directory
164   -s, --site=SITE                 base name of the site file
165 EOF
166 }
167
168 print_help_media() {
169     cat <<EOF
170 Usage: $progname media [OPTIONS]
171 Copy media to the output directory.
172
173   -o, --output=DIR                the output directory
174   -s, --site=SITE                 base name of the site file
175 EOF
176 }
177
178 echo_verbose() {
179     if [ "x$site_verbose" = "x1" ]; then
180         echo "$1"
181     fi
182 }
183
184 mkdir_p() {
185     __dir__='';
186     echo $1 | sed -e 's/\//\n/g' | while read d; do
187         __dir__="$__dir__$d/"
188         if [ ! -d "$__dir__" ]; then
189             mkdir "$__dir__" || error "Could not create directory"
190         fi
191     done || exit 1;
192 }
193
194 urlencode() {
195     echo "$1" | awk --posix '
196 BEGIN {
197   for (i = 1; i <= 256; i++) {
198     bytes[sprintf("%c", i)] = i;
199   }
200 }
201 {
202   for (i = 1; i <= length($0); i++) {
203     c = substr($0, i, 1);
204     if (c ~ /[a-zA-Z0-9:_\.\-\/]/)
205       printf("%s", c);
206     else
207       printf("%%%02X", bytes[c]);
208   }
209 }
210 '
211 }
212
213 locate_site_file() {
214     site_directory=`pwd`
215     while [ "x${site_directory}" != "x" -a ! -f "${site_directory}/${site_site}.site" ]; do
216         if [ "x${site_directory}" = "x/" ]; then
217             error "Could not locate ${site_site}.site"
218         else
219             site_directory=`dirname "$site_directory"`
220         fi
221     done
222     site_directory=$( (cd "$site_directory" && pwd) )
223     site_file="${site_directory}/${site_site}.site"
224     if [ ! -f "$site_file" ]; then
225         error "Could not locate ${site_site}.site"
226     fi
227 }
228
229 create_cache() {
230     longopts='
231       -lsite:
232       -lverbose
233       -lhelp
234     ';
235     options=`getopt -qn$progname $longopts -- s:vh "$@"`
236     if [ "$?" != "0" ]; then print_help_cache 1>&2; exit 1; fi
237     eval set -- "$options";
238     while [ "$1" != "--" ]; do
239         case "$1" in
240             -s | --site)
241                 site_site="$2";;
242             -v | --verbose)
243                 site_verbose=1;;
244             -h | --help)
245                 print_help_cache
246                 exit 0;;
247             --)
248                 print_help_cache 1>&2
249                 exit 1;;
250         esac
251         shift
252     done
253     shift
254     locate_site_file
255     site_cache="${site_directory}/${site_site}.cache"
256     echo_verbose "Creating ${site_directory}/${site_site}.cache.in"
257     (
258         echo '<cache:cache xmlns:cache="http://projectmallard.org/cache/1.0/"'
259         echo '             xmlns:site="http://projectmallard.org/site/1.0/"'
260         echo '             xmlns="http://projectmallard.org/1.0/">'
261         find "$site_directory" -name '*.page' | while read page; do
262             page_esc=$(urlencode "$page" | sed -e 's/\&/\&amp;/g' -e 's/</\&lt;/g' -e "s/'/\&apos;/g")
263             page_dir=$(urlencode $(dirname $(echo "$page" | cut -c${#site_directory}- | cut -c2-)))
264             if [ "x${page_dir}" != "x/" ]; then
265                 page_dir="$page_dir/"
266             fi
267             echo "<page cache:href='file://$page_esc' site:dir='${page_dir}'/>"
268         done
269         echo '</cache:cache>'
270     ) > "${site_cache}.in"
271     echo_verbose "Creating ${site_directory}/${site_site}.cache"
272     echo "$XSL_CACHE" | xsltproc --xinclude - "${site_cache}.in" | xmllint --format - > "$site_cache"
273 }
274
275 create_css_xsl() {
276     echo '
277 <xsl:stylesheet
278   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
279   xmlns:mal="http://projectmallard.org/1.0/"
280   version="1.0">
281 <xsl:import href="'$(pkg-config --variable xsltdir yelp-xsl)'/gettext/gettext.xsl"/>
282 <xsl:import href="'$(pkg-config --variable xsltdir yelp-xsl)'/common/theme.xsl"/>
283 <xsl:import href="'$(pkg-config --variable xsltdir yelp-xsl)'/mallard/html/mal2html-css.xsl"/>
284 <xsl:output method="text"/>
285 <xsl:template match="/">
286   <xsl:call-template name="mal2html.css.content"/>
287 </xsl:template>'
288     if [ "x$site_custom" != "x" ]; then
289         echo "<xsl:include href='${site_directory}/${site_custom}'/>"
290     fi;
291     echo '</xsl:stylesheet>'
292 }
293
294 create_css() {
295     longopts='
296       -lsite:
297       -loutput:
298       -lverbose
299       -lhelp
300     ';
301     options=`getopt -qn$progname $longopts -- s:o:vh "$@"`
302     if [ "$?" != "0" ]; then print_help_css 1>&2; exit 1; fi
303     eval set -- "$options";
304     while [ "$1" != "--" ]; do
305         case "$1" in
306             -s | --site)
307                 site_site="$2";;
308             -o | --output)
309                 site_output_dir=$( (cd "$2" && pwd) );;
310             -v | --verbose)
311                 site_verbose=1;;
312             -h | --help)
313                 print_help_css
314                 exit 0;;
315             --)
316                 print_help_css 1>&2
317                 exit 1;;
318         esac
319         shift
320     done
321     shift
322     locate_site_file
323     if [ "x$site_output_dir" = "x" ]; then
324         site_output_dir="$site_directory"
325     fi
326     site_root=`echo "$XSL_GET_ROOT" | xsltproc - "$site_file"`
327     site_custom=`echo "$XSL_GET_CUSTOM" | xsltproc - "$site_file"`
328     echo_verbose "Creating ${site_output_dir}/index.css"
329     create_css_xsl | xsltproc -o "${site_output_dir}/index.css" - "${site_directory}/index.page"
330 }
331
332 copy_media() {
333     longopts='
334       -lsite:
335       -loutput:
336       -lverbose
337       -lhelp
338     ';
339     options=`getopt -qn$progname $longopts -- s:o:vh "$@"`
340     if [ "$?" != "0" ]; then print_help_media 1>&2; exit 1; fi
341     eval set -- "$options";
342     while [ "$1" != "--" ]; do
343         case "$1" in
344             -s | --site)
345                 site_site="$2";;
346             -o | --output)
347                 site_output_dir=$( (cd "$2" && pwd) );;
348             -v | --verbose)
349                 site_verbose=1;;
350             -h | --help)
351                 print_help_media
352                 exit 0;;
353             --)
354                 print_help_media 1>&2
355                 exit 1;;
356         esac
357         shift
358     done
359     shift
360     locate_site_file
361     if [ "x$site_output_dir" = "x" ]; then
362         error "No output directory given"
363     fi
364     for page in $(find $(pwd) -name '*.page'); do
365         page_dir=$(dirname $(echo "$page" | cut -c${#site_directory}- | cut -c2-))/
366         page_base=$(basename "$page" .page)
367         page_outdir="$site_output_dir$page_dir"
368         mkdir_p $(dirname "$page_output")
369         echo "$XSL_MALLARD_MEDIA" | xsltproc --xinclude - "$page" | while read media; do
370             media_output="$page_outdir$media"
371             echo_verbose "Creating $media_output"
372             cp ".$page_dir$media" "$media_output"
373         done
374     done
375 }
376
377 copy_icons() {
378     if [ "x$doc_copy_icons" = "x1" ]; then
379         if [ "x$doc_icons_admon_path" = "x" ]; then
380             p="$pkgdatadir/icons/hicolor/"
381             if [ "x$doc_icons_admon_size" != "x" ]; then
382                 doc_icons_admon_path="${p}${doc_icons_admon_size}x${doc_icons_admon_size}/status"
383             else
384                 doc_icons_admon_path="${p}48x48/status"
385             fi
386             unset p
387         fi
388         for doc_icon in $(echo $doc_icons_to_copy | tr ' ' '\n' | grep '^admon-' | sort | uniq); do
389             doc_icon_file="${doc_icon}.png"
390             cmd="cp \"$doc_icons_admon_path/$doc_icon_file\" \"$doc_outdir/$doc_icon_file\""
391             echo_verbose "$cmd"
392             eval "$cmd"
393         done
394     fi
395 }
396
397 list_icons() {
398     while [ "$#" != "0" ]; do
399         if [ -d "$1" ]; then
400             list_icons "$1/"*.page
401         else
402             echo "$XSL_ICONS" | xsltproc --nonet --xinclude - "$1"
403         fi
404         shift
405     done | sort | uniq
406 }
407
408 list_media() {
409     if [ "x$(echo "$1" | sed -e 's/.*\.//')" = "xpage" -o -d "$1" ]; then
410         XSL_MEDIA="$XSL_MALLARD_MEDIA"
411     else
412         XSL_MEDIA="$XSL_DOCBOOK_MEDIA"
413     fi
414     while [ "$#" != "0" ]; do
415         if [ -d "$1" ]; then
416             list_media "$1/"*.page
417         else
418             doc_indir=$(dirname "$1")
419             if [ "$doc_indir" = "." ]; then
420                 doc_indir=""
421             else
422                 doc_indir="$doc_indir/"
423             fi
424             echo "$XSL_MEDIA" | xsltproc --nonet --xinclude - "$1" \
425                 | while read doc_media; do
426                 echo "$doc_indir$doc_media"
427             done
428         fi
429         shift
430     done | sort | uniq
431 }
432
433 convert_html_xsl() {
434     echo '
435 <xsl:stylesheet
436   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
437   xmlns:site="http://projectmallard.org/site/1.0/"
438   version="1.0">
439 <xsl:import href="'${datadir}/mallard-site-tool/site2html.xsl'"/>'
440     if [ "x$site_custom" != "x" ]; then
441         echo "<xsl:include href='${site_directory}/${site_custom}'/>"
442     fi;
443     echo '</xsl:stylesheet>'
444 }
445
446 convert_html() {
447     site_format="$1"
448     shift
449     longopts='
450       -lsite:
451       -loutput:
452       -lverbose
453       -lhelp
454     ';
455     options=`getopt -qn$progname $longopts -- s:o:vh "$@"`
456     if [ "$?" != "0" ]; then print_help_html 1>&2; exit 1; fi
457     eval set -- "$options";
458     while [ "$1" != "--" ]; do
459         case "$1" in
460             -s | --site)
461                 site_site="$2";;
462             -o | --output)
463                 site_output_dir=$( (cd "$2" && pwd) );;
464             -v | --verbose)
465                 site_verbose=1;;
466             -h | --help)
467                 print_help_cache
468                 exit 0;;
469             --)
470                 print_help_cache 1>&2
471                 exit 1;;
472         esac
473         shift
474     done
475     shift
476     locate_site_file
477     if [ "x$site_output_dir" = "x" ]; then
478         site_output_dir="$site_directory"
479     fi
480     site_cache="${site_directory}/${site_site}.cache"
481     site_root=`echo "$XSL_GET_ROOT" | xsltproc - "$site_file"`
482     site_custom=`echo "$XSL_GET_CUSTOM" | xsltproc - "$site_file"`
483     if [ "x$site_root" = "x" ]; then
484         site_root="file://"$(urlencode "$site_directory")
485     fi
486
487     for page in $(find $(pwd) -name '*.page'); do
488         page_dir=$(dirname $(echo "$page" | cut -c${#site_directory}- | cut -c2-))/
489         page_base=$(basename "$page" .page)
490         page_output="$site_output_dir$page_dir$page_base.$site_format"
491         mkdir_p $(dirname "$page_output")
492         echo_verbose "Creating $page_output"
493         convert_html_xsl | xsltproc \
494             --xinclude \
495             -o "$page_output" \
496             --stringparam mal.site.dir "$page_dir" \
497             --stringparam mal.site.root "$site_root" \
498             --stringparam mal.cache.file "$site_cache" \
499             - "$page"
500     done
501 }
502
503 site_site="index"
504
505 command="$1";
506 if [ "x$command" = "x" ]; then
507     print_help 1>&2;
508     exit 1;
509 fi;
510 shift;
511 if [ "x$command" = "xhelp" -o "x$command" = "x--help" -o "x$command" = "x-h" ]; then
512     print_help;
513     exit 0;
514 elif [ "x$command" = "xhtml" ]; then
515     convert_html "$command" $@;
516 elif [ "x$command" = "xcache" ]; then
517     create_cache $@;
518 elif [ "x$command" = "xcss" ]; then
519     create_css $@;
520 elif [ "x$command" = "xmedia" ]; then
521     copy_media $@;
522 else
523     print_help 1>&2;
524     exit 1;
525 fi;
526