<!--  vim: set sw=2 sts=2 et ft=docbk:

  Part of the A-A-P recipe executive: Tutorial - Publishing a Web site

  Copyright (C) 2002-2003 Stichting NLnet Labs
  Permission to copy and use this file is specified in the file COPYING.
  If this file is missing you can find it here: http://www.a-a-p.org/COPYING

-->

<para>
If you are maintaining a web site it is often a good idea to edit the files
on your local system.  After trying out the changes you then need to upload
the changed files to the web server.  A-A-P can be used to identify the files
that changed and upload these files only.  This is called publishing.
</para>

<bridgehead>Uploading The Files</bridgehead>

<para>
Here is an example of a recipe:
</para>

<programlisting>
   Files = index.html
           project.html
           links.html
           images/logo.png
   :attr {publish = scp://user@ftp.foo.org/public_html/%file%} $Files
</programlisting>

<para>
That's all.  You just need to specify the files you want to publish and
the URL that says how and where to upload them to.  Now "aap publish" will
find out which files have changed and upload them:
</para>
<literallayout>    % <userinput>aap publish</userinput>
    Aap: Uploading ['/home/mool/www/foo/index.html'] to scp://user@ftp.foo.org/public_html/index.html
    Aap: scp '/home/mool/www/vim/index.html' 'user@ftp.foo.org:public_html/index.html'
    Aap: Uploaded "/home/mool/www/vim/index.html" to "scp://user@ftp.foo.org/public_html/index.html"
    %
</literallayout>
<para>
The first time you execute the recipe all files will be uploaded.  &Aap; will
create the "images" directory for you.  If you had already uploaded the files
and want to avoid doing it again, first run the recipe with: "aap publish
--touch".  &Aap; will compute the signatures of the files as they are now and
remember them.  Only files that are changed will be uploaded from now on.
</para>

<para>
  The
  <link linkend="cmd-attr">:attr</link>
  command uses its first argument as an attribute and further
arguments as file names.  It will attach the attribute to each of the files.
In this case the "publish" attribute is added, which specifies the URL where
to upload a file to.  In the example the "scp" protocol is used, which is a
good method for uploading files to a public server.  "ftp" can be used as
well, but this means your password will go over the internet, which is not
safe.  The special item "%file%" is replaced with the name of the file being
published.
</para>

<bridgehead>Generating a HTML File</bridgehead>

<para>
It is common for HTML files to consist of a standard header, a body with
the useful info and a footer.  You don't want to manually add the header and
footer to each page.  When the header changes you would have to make the same
change in many different files.  Instead, use the recipe to generate the HTML
files.
</para>

<para>
Let's start with a simple example: Generate the index.html file.  Put the
common header, containing a logo and navigation links, in "header.part".  
The footer, containing contact info for the maintainer, goes in "footer.part".
The useful contents of the page goes in "index_body.part".  Now you can use
this recipe to generate "index.html" and publish it:
</para>

<programlisting>
   Files =    index.html
              images/logo.png
   :attr {publish = scp://user@ftp.foo.org/public_html/%file%} $Files

   all: $Files

   publish: $Files
       :publishall

   index.html: header.part index_body.part footer.part
       :cat $source &gt;! $target
</programlisting>

<para>
Notice that only the published files are put in the "Files" variable.  These
files get a "publish" attribute, which tells &Aap; that these are the files
that need to be uploaded.  The ".part" files are not published, thus they do
not get the "publish" attribute.
</para>

<para>
Three dependencies follow.  The "all" target is the virtual target we have
seen before.  It specifies that the default work for this recipe is to update
the files in the "Files" variable.  This means you don't accidentally upload
the files by running "aap" without arguments.  The normal way of use is to run
"aap", check if the produced HTML file looks OK, then use "aap publish" to
upload the file.
</para>
<para>
  For "index.html" a target is specified with a build command.  The
  <link linkend="cmd-cat">:cat</link>
command concatenates the source files.  "$source" stands for the source files
used in the dependency: "header.part, "index_body.part" and "footer.part".
The resulting text is written to "$target", which is the target of the
dependency, thus "index.html".  The "&gt;!" is used to redirect the output of
the
  <link linkend="cmd-cat">:cat</link>
command and overwrite any existing result.  This works just like
the Unix "cat" command.
</para>
<para>
  In the dependency with the "publish" target the
  <link linkend="cmd-publishall">:publishall</link>
  command is used.
This command goes through all the files which were given a "publish" attribute
with the
<link linkend="cmd-attr">:attr</link>
command.  Note that this does not work:
</para>
<programlisting>
   # This won't work.
   Files = index.html {publish = scp://user@ftp.foo.org/public_html/%file%}
</programlisting>
<para>
Using a "publish" attribute in an assignment will not make it used with the
<link linkend="cmd-publishall">:publishall</link>
command.
</para>

<bridgehead>Using ":rule" to Generate Several HTML Files</bridgehead>

<para>
Your web site contains several pages, thus you need to specify how to generate
each HTML page.  This quickly becomes a lot of typing.  We would rather
specify once how to make a "xxx.html" file from a "xxx_body.part" file, and
then give the list of names to use for "xxx" (if you have assocations with the
name "xxx_body.part" that is your own imagination! :-).  This is how it's
done:
</para>

<programlisting>
   Files =    *.html
              images/*.png
   :attr {publish = scp://user@ftp.foo.org/public_html/%file%} $Files

   all: $Files

   publish: $Files
       :publishall

   :rule %.html : header.part %_body.part footer.part
       :cat $source &gt;! $target
</programlisting>

<para>
This is very similar to the example that only generates the "index.html" file.
The first difference is in the value of "Files": It contains wildcards.
These wildcards are expanded when they are used where a file name is expected.
The expansion is not done in the assignment!  More about that later.
In the three places where $Files is used the wildcard expansion results in a
list of all "*.html" files in the current directory and all "*.png" files in
the "images" directory.
</para>

<para>
The second difference is that there is no specific dependency for the
"index.html" file but a
<link linkend="cmd-rule">:rule</link>
command.  It looks very much the same, but the
word "index" has been replaced by a percent character.  You could read the
rule command as a dependency where the "%" stands for "anything".  In the
example the target is "anything.html" and in the sources we find
"anything_body.part".  Obviously these two occurrences of "anything" are the
same word.
</para>

<para>
If you have made HTML pages, you know they contain a title.  We ignored that
until now.  The following recipe will handle a title, stored in the file
"xxx_title.part".  You also need a file "start.part", which contains the HTML
code that goes before the title.
</para>

<programlisting>
   Files =    *.html
              images/*.png
   :attr {publish = scp://user@ftp.foo.org/public_html/%file%} $Files

   all: $Files

   publish: $Files
       :publishall

   :rule %.html : start.part %_title.part header.part %_body.part footer.part
       :cat $source &gt;! $target
</programlisting>

<para>
  Notice that "%" is now used three times in the
  <link linkend="cmd-rule">:rule</link>
  command.  It stands for
the same word every time.
</para>
<para>
After writing this recipe you can forget what changes you made to what file.
A-A-P will take care of generating and uploading those HTML files that are
affected.  For example, if you change "header.part", all the HTML files are
generated and uploaded.  If you change "index_title.part" only "index.html"
will be done.
</para>
<para>
There is one catch: You must create an (empty) xxx.html file the first time,
otherwise it will not be found with "*.html".  And you have to be careful not
to have other "xxx.html" files in this directory.  You might want to
explicitly specify all the HTML files instead of using wildcards.
</para>
<para>
The same problem with wildcards happens for the image files.  There is a
solution for this: use the
<link linkend="python-get-html-images">get_html_images()</link> function.
You can find an example in <xref linkend="publish-images"/>.
</para>
<para>
A similar recipe is actually used to update the A-A-P website.  It's a bit
more complicated, because not all pages use the same header.
</para>
