# Demonstration of linking

# Overview

Forrest has many powerful techniques for linking between documents and for managing the site navigation. This document demonstrates those techniques. The document "Menus and Linking" has the full details.

# Building and maintaining consistent URI space

When Forrest builds your site, it starts from the front page. Like a robot, it traverses all of the links that it finds in the documents and builds the corresponding pages. Any new links are further traversed.

Sometimes those links lead to documents that are generated directly from xml source files, sometimes they are generated from other source via an intermediate xml format. Other times the links lead to raw un-processed content.

The site navigation configuration file "`site.xml`" provides a way to manage this URI space. In the future, when documents are re-arranged and renamed, the site.xml configuration will enable this smoothly.

# Mapping the local resource space to the final URI space

For both generated and raw (un-processed) files, the top-level of the URI space corresponds to the "`content/xdocs/`" directory, i.e. the location of the "`site.xml`" configuration file.

In versions prior to 0.7 raw un-processed content was stored in the "`content/`" directory. In 0.7 onwards, raw un-processed data is stored alongside the xdocs. In addition, in 0.6 and earlier, HTML documents could be stored in the xdocs directory and served without processing. If you you wish to emulate the behaviour of 0.6 and earlier see the next section.

A diagram will help.

    The resource space          ==============>    The final URI space
    ------------------                             -------------------
    Generated content ...
     content/xdocs/index.xml                       index.html
     content/xdocs/samples/index.xml               samples/index.html
     content/xdocs/samples/faq.xml                 samples/faq.html
     content/xdocs/test1.html                      test1.html
     content/xdocs/samples/test3.html              samples/test3.html
     content/xdocs/samples/subdir/test4.html       samples/subdir/test4.html

    Raw un-processed content ...
     content/xdocs/hello.pdf                       hello.pdf
     content/xdocs/hello.sxw                       hello.sxw
     content/xdocs/subdir/hello.sxw                subdir/hello.sxw

## How Plugins May Affect The URI Space

By using Forrest Input Plugins you can process some file formats, such as OpenOffice.org documents and produce processed content from them. For example, the file `content/xdocs/hello.sxw` can be used to produce a skinned version of the document at with the name `hello.html`. Similarly, you can use Forrest Output Plugins to create different output formats such as PDF, in this case `content/xdocs/hello.sxw` can produce `hello.pdf`.

However, this does not affect the handling of raw content. That is, you can still retrieve the raw un-processed version with, for example, `hello.sxw`. If you want to prevent the user retrieving the un-processed version you will have to create matchers that intercept these requests within your project sitemap.

# Basic link to internal generated pages

When this type of link is encountered, Forrest will look for a corresponding xml file, relative to this document (i.e. in `content/xdocs/samples/`).

A generated document in the current directory, which corresponds to `content/xdocs/samples/sample.html` ...

    <a href="sample.html">sample.html
    </a>

In a sub-directory, which corresponds to `content/xdocs/samples/subdir/index.html` ...

    <a href="subdir/index.html">subdir/index.html
    </a>

# Basic link to raw un-processed content

Raw content files are not intended for any processing, they are just linked to (e.g. pre-prepared PDFs, zip archives). These files are placed alongside your normal content in the "`content/xdocs`" directory.

A raw document in the current directory, which corresponds to `content/xdocs/samples/helloAgain.pdf` ...

    <a href="helloAgain.pdf">helloAgain.pdf
    </a>

A raw document in a sub-directory, which corresponds to `content/xdocs/samples/subdir/hello.zip` ...

    <a href="subdir/hello.zip">subdir/hello.zip
    </a>

A raw document at the next level up, which corresponds to `content/hello.pdf` ...

    <a href="../hello.pdf">../hello.pdf
    </a>

## Serving (X)HTML content without Skinning

Prior to version 0.7, the raw un-processed content was stored in the "`content/`" directory. In 0.7 onwards, raw un-processed data is stored alongside the xdocs. In addition in 0.6 and earlier, HTML files could be stored in the xdocs directory and they would be served without further processing. As described above, this is not the case in 0.7 where HTML files are, by default, skinned by Forrest.

If you you wish to emulate the behaviour of 0.6 and earlier then you must add the following to your project sitemap.

    <map:match pattern="**.html">
     <map:select type="exists">
      <map:when test="{properties:content}{0}">
        <map:read src="{properties:content}/{0}" mime-type="text/html"/>
        <!--
          Use this instead if you want JTidy to clean up your HTML
          <map:generate type="html" src="{properties:content}/{0}" />
          <map:serialize type="html"/>
        -->
      </map:when>
      <map:when test="{properties:content.xdocs}{0}">
        <map:read src="{properties:content.xdocs}/{0}" mime-type="text/html"/>
        <!--
          Use this instead if you want JTidy to clean up your HTML
          <map:generate type="html" src="{properties:content.xdocs}/{0}" />
          <map:serialize type="html"/>
        -->
      </map:when>
     </map:select>
    </map:match>

The above allows us to create links to un-processed skinned files stored in the `{properties:content}` or `{properties:content.xdocs}` directory. For example: <a href="/test1.html">HTML content</a>. However, it will break the 0.7 behaviour of skinning HTML content. For this reason the old ".ehtml" extension can be used to embed HTML content in a Forrest skinned site

Note that you can change the matchers above to selectively serve some content as raw un-processed content, whilst still serving other content as skinned documents. For example, the following snippet would allow you to serve the content of an old, deprecated site without processing from Forrest, whilst still allowing all other content to be processed by Forrest in the normal way:

    <map:match pattern="old_site/**.html">
     <map:select type="exists">
      <map:when test="{properties:content}{1}.html">
        <map:read src="{properties:content}/{1}.html" mime-type="text/html"/>
        <!--
          Use this instead if you want JTidy to clean up your HTML
          <map:generate type="html" src="{properties:content}/{0}" />
          <map:serialize type="html"/>
        -->
      </map:when>
    </map:match>

For example, HTML content.

# Full URL to external documents

A full URL ...

    <a href="http://forrest.apache.org/">http://forrest.apache.org/
    </a>

A full URL with a fragment identifier ...

    <a href="http://forrest.apache.org/faq.html#link_raw">http://forrest.apache.org/faq.html#link_raw
    </a>

Note that Forrest does not traverse external links to look for other links.

# Using site.xml to manage the links

As you will have discovered, using pathnames with ../../ etc. will get very nasty. Real problems occur when you use a smart text editor that tries to manage the links for you. For example, it will have trouble linking to the raw content files which are not yet in their final location.

Links and filenames are bound to change and re-arrange. It is essential to only change those links in one central place, not in every document.

The "`site.xml`" configuration file to the rescue. It maps symbolic names to actual resources.

## Basic link to internal generated pages

This single entry ...

    <index label="Index" href="index.html"/>

enables a simple link to a generated document, which corresponds to `content/xdocs/index.xml` ...

    <a href="site:index">site:index
    </a>

## Group some items

This compound entry ...

      <samples label="Samples" href="samples/" tab="samples">
        <faq label="FAQ" href="faq.html"/>
        ...
      </samples>

enables a link to a generated document, which corresponds to `content/xdocs/samples/index.xml` ...

    <a href="site:samples">site:samples
    </a>

and a link to a generated document, which corresponds to `content/xdocs/samples/faq.xml` ...

    <a href="site:faq">site:faq
    </a>
    which can also be a complete reference
    <a href="site:samples/faq">site:samples/faq
    </a>

## Fragment identifiers

This compound entry ...

      <samples label="Samples" href="samples/" tab="samples">
        <sample label="Apache document" href="sample.html">
          <top href="#top"/>
          <section href="#section"/>
        </sample>
        ...
      </samples>

enables a link to a fragment identifier within the `samples/sample.html` document ...

    <a href="site:samples/sample/section">site:samples/sample/section
    </a>

## Define items for raw content

This entry ...

    <hello_print href="hello.pdf"/>

enables a link to a raw document, which corresponds to `content/hello.pdf` ...

    <a href="site:hello_print">site:hello_print
    </a>

## External links

This compound entry ...

      <external-refs>
        <forrest href="http://forrest.apache.org/">
          <linking href="docs/linking.html"/>
          <webapp href="docs/your-project.html#webapp"/>
        </forrest>
      </external-refs>

enables a link to an external URL ...

    <a href="ext:forrest">ext:forrest
    </a>

and a link to another external URL ...

    <a href="ext:linking">ext:linking
    </a>
    which can also be a complete reference
    <a href="ext:forrest/linking">ext:forrest/linking
    </a>

and a link to another external URL with a fragment identifier ...

    <a href="ext:webapp">ext:webapp
    </a>
    which can also be a complete reference
    <a href="ext:forrest/webapp">ext:forrest/webapp
    </a>

# Images

Images (and other resources) are handled by the main/webapp/resource.xmap sitemap. It uses the main/webapp/locationmap.xml to look in various locations for images. As usual, the first match wins.

Here is the locationmap snippet ...

        <match pattern="project.images.**.*">
          <select>
            <location src="{properties:resources.images}{1}.{2}" />
            <location src="{properties:content}../resources/images/{1}.{2}" />
            <location src="{properties:content.xdocs}images/{1}.{2}" />
            <location src="{properties:content.xdocs}{1}.{2}" />
          </select>
        </match>

Which means look first in a project-defined images directory, then in the default location (which is usually src/documentation/resources/images/), then in the old default location (src/documentation/content/xdocs/images/), then relative to the root of your xdocs.

The document author specifies the final image locations with these various "`src=`" links. Behind-the-scenes Cocoon handles the requests using the sitemap and locationmap.

This sample has the following image locations:

        src/documentation/resources/images/ellipse-2.svg
        src/documentation/resources/images/icon-a.png
        src/documentation/resources/images/icon-b.png
        src/documentation/resources/images/sub-dir/icon-c.png
        src/documentation/content/xdocs/images/icon-e.png
        src/documentation/content/xdocs/samples/icon-d.png
        src/documentation/content/xdocs/samples/ellipse.svg
        src/documentation/content/xdocs/samples/cocoon-pyramid.aart

Here is the effect of the various image links ...

1. Icon

   `<img src="/images/icon-a.png"` ... The source file is found in src/documentation/resources/images/ directory.

2. Icon

   `<img src="/images/sub-dir/icon-c.png"` ... The source file is found in src/documentation/resources/images/sub-dir/ directory.

3. Icon

   `<img src="/images/icon-e.png"` ... The source file is not found in the normal src/documentation/resources/images/ so Cocoon looks in the next location and finds the source in src/documentation/content/xdocs/images/ directory. This supports backward-compatibility for this old default location.

4. Icon

   `<img src="images/icon-a.png"` ... same as example 1 above. Except this time the generated image is relative to the document.

5. Icon

   `<img src="../images/icon-a.png"` ... Relative reference. Forrest "absolutizes" the URLs to be like the URLs in examples 1 and 2 and 3. Then Cocoon looks in the normal locations as described above. The source file is found in src/documentation/resources/images/ directory.

6. Icon

   `<img src="../../images/icon-b.png"` ... Broken relative reference (it points up beyond the document root). Never mind, Forrest "absolutizes" the URLs to be like the URLs in examples 1 and 2 and 3. The source file is found in src/documentation/resources/images/ directory. However there is a problem here. When using Forrest in command-line mode, the image will be generated outside the document directory. It is better to use absolute /image/ URLs or be very careful about using such relative links (Forrest will not report an error).

7. Icon

   `<img src="/images/ellipse-2.png"` ... Cocoon tried the various locations for a PNG image called ellipse-2.png but did not find one anywhere. So the next sitemap match looks for a corresponding ellipse-2.svg and generates the PNG image on-the-fly. The source file is found in src/documentation/resources/images/ directory.

The image links shown above are handled by the resources.xmap using special matches for the "images" directory in the URI.

The main/webapp/resources.xmap has another section to deal specifically with PNG images. It looks first for an SVG source file which will be used to generate the PNG image. If that is not found then it looks for an ASCII art source file. Then looks for a pre-prepared PNG image.

1. Icon

   `<img src="ellipse.png"` ... Cocoon tried the various locations for a PNG image called ellipse-2.png but did not find one anywhere. So the next sitemap match looks for a corresponding ellipse-2.svg and generates the PNG image on-the-fly. The source file is found in the current directory src/documentation/content/xdocs/samples/

2. Icon

   `<img src="cocoon-pryamid.png"` ... ASCII Art. Cocoon did not find a PNG image, nor an SVG file. So the next sitemap match looks for a corresponding cocoon-pryamid.aart and generates the PNG image on-the-fly. The source file is found in the current directory src/documentation/content/xdocs/samples/

3. Icon

   `<img src="icon-d.png"` ... Relative to this document. The source file is found in the current directory src/documentation/content/xdocs/samples/

You might wonder why the above images all show correctly in dynamic 'forrest run' mode, but some appear to be broken during static docs generation 'forrest site' mode. The latter is for generating a set of static docs for deployment to a server. If you used URLs beginning with a slash, "/images/...", then that is their location. So the generated docs on the "forrest zone" demos appear to be broken.