
Successful software applications are rarely produced by a team of one. When we're talking about any software worth writing, we're usually dealing teams of collaborating developers ranging anywhere in size from a handful of programmers working in a small team to hundreds or thousands of programmers working in large distributed environment. Most open source projects (such as Maven) succeed or fail based on the presence or absence of well written documentation for a widely-distributed, ad-hoc collection of users and developers. In all environments it is important for projects to have an easy way to publish and maintain online documentation. Software development is primarily an exercise in collaboration and communication, and publishing a Maven site is one way to make sure that your project is communicating with your end-users.
A web site for an open source project is often the foundation for both the end-user and developer communities alike. End-users look to a project's web site for tutorials, user guides, API documentation, and mailing list archives, and developers look to a project's web site for design documents, code reports, issue tracking, and release plans. Large open-sources projects may be integrated with wikis, issue trackers, and continuous integration systems which help to augment a project's online documentation with material that reflects the current status of ongoing development. If a new open source project has an inadequate web site which fails to convey basic information to prospective users, if often is a sign that the project in question will fail to be adopted. In other words, for an open source project, the site and the documentation are as important to the formation of a community as the code itself.
Maven can be used to create a project web site to capture information which is relevant to both the end-user and the developer audience. Out of the box, Maven can generate reports on everything from unit test failures to package coupling to reports on code quality. Maven provides you with the ability to write simple web pages and render those pages against a consistent project template. Maven can publish site content in multiple formats including XHTML and PDF. Maven can be used to generate API document and can also be used to embedded Javadoc and source code in your project's binary release archive. Once you've used Maven to generate all of your project's end-user and developer documentation, you can then use Maven to publish your web site to a remote server.
To illustrate the process of building a project website, create a sample Maven project with the archetype plugin:
$ mvn archetype:create -DgroupId=com.sonatype.maven -DartifactId=sample-project
This creates the simplest possible Maven project with a one Java
class in src/main/java and a simple
POM. You can then build a Maven site by simply running
mvn site. To build the site and preview the result in a browser, you can
run mvn site:run, this will build the site and start an
embedded instance of Jetty.
$ cd sample-project $ mvn site:run [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'site'. [INFO] ------------------------------------------------------------------------ [INFO] Building sample-project [INFO] task-segment: [site:run] (aggregator-style) [INFO] ------------------------------------------------------------------------ [INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'. [INFO] Setting property: velocimacro.messages.on => 'false'. [INFO] Setting property: resource.loader => 'classpath'. [INFO] Setting property: resource.manager.logwhenfound => 'false'. [INFO] [site:run] 2008-04-26 11:52:26.981::INFO: Logging to STDERR via org.mortbay.log.StdErrLog [INFO] Starting Jetty on http://localhost:8080/ 2008-04-26 11:52:26.046::INFO: jetty-6.1.5 2008-04-26 11:52:26.156::INFO: NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet 2008-04-26 11:52:26.244::INFO: Started SelectChannelConnector@0.0.0.0:8080
Once Jetty starts and is listening to port 8080, you can see the project's site when you go to http://localhost:8080/ in a web browser. You can see the results in Figure 15.1, “Simple Generated Maven Site”.
If you click around on this simple site, you'll see that it isn't
very helpful as a real project site. There's just nothing there (and it
doesn't look very good). Since the sample-project
hasn't configured any developers, mailing lists, issue tracking providers,
or source code repositories, all of these pages on the project site will
have no information. Even the index page of the site states, "There is
currently no description associated with this project". To customize the
site, you'll have to start add content to the project and to the project's
POM.
If you are going to use the Maven Site plugin to build your project's site, you'll want to customize it. You will want to populate some of the important fields in the POM that tell Maven about the people participating in the project, and you'll want to customize the left-hand navigation menu and the links visible in the header of the page. To customize the contents of the site and affect the contents of the left-hand navigation menu, you will need to edit the site descriptor.
When you add content to the site, you are going to want to modify the left-hand navigation menu that is generated with your site. The following site descriptor customizes the logo in the upper left-hand corner of the site. In addition to customizing the header of the site, this descriptor adds a menu section to the left-hand navigation menu under the heading "Sample Project". This menu contains a single link to an overview page.
Example 15.1. An Initial Site Descriptor
<project name="Sample Project"> <bannerLeft> <name>Sonatype</name> <src>images/logo.png</src> <href>http://www.sonatype.com</href> </bannerLeft> <body> <menu name="Sample Project"> <item name="Overview" href="index.html"/> </menu> <menu ref="reports"/> </body> </project>
This site descriptor references one image. This
logo.png image should be placed in
${basedir}/src/site/resources/images. In addition to
the change to the site descriptor, you'll want to create a simple
index.apt page in
${basedir}/src/site/apt. Put the following content in
index.apt, it will be transformed to the
index.html and serve as the first page a user sees
when they come to your project's Maven-generated web site.
Welcome to the Sample Project, we hope you enjoy your time on this project site. We've tried to assemble some great user documentation and developer information, and we're really excited that you've taken the time to visit this site. What is Sample Project Well, it's easy enough to explain. This sample project is a sample of a project with a Maven-generated site from Maven: The Definitive Guide. A dedicated team of volunteers help maintain this sample site, and so on and so forth.
To preview the the site, run mvn clean site followed by mvn site:run:
$ mvn clean site $ mvn site:run
Once you do this, load the page in a browser by going to http://localhost:8080. You should see something similar to the screenshot in Figure 15.2, “Customized Sample Project Web Site”.
To customize the graphics which appear in the upper left-hand and
right-hand corners of the page, you can use the
bannerLeft and bannerRight
elements in a site descriptor.
Example 15.2. Adding a Banner Left and Banner Right to Site Descriptor
<project name="Sample Project"> <bannerLeft> <name>Left Banner</name> <src>images/banner-left.png</src> <href>http://www.google.com</href> </bannerLeft> <bannerRight> <name>Right Banner</name> <src>images/banner-right.png</src> <href>http://www.yahoo.com</href> </bannerRight> ... </project>
Both the bannerLeft and
bannerRight elements take name,
src, and href child elements. In
the site descriptor shown above, the Maven Site plugin will generate a
site with banner-left.png in the left-hand corner
of the page and banner-right in the right-hand corner of the page. Maven
is going to look in
${basedir}/src/site/resources/images for these
images.
To customize the contents of the navigation menu, use the
menu element with item child
elements. The menu element adds a section to the
left-hand navigation menu. Each item is rendered as a link in that
menu.
Example 15.3. Creating Menu Items in a Site Descriptor
<project name="Sample Project"> ... <body> <menu name="Sample Project"> <item name="Introduction" href="index.html"/> <item name="News" href="news.html"/> <item name="Features" href="features.html"/> <item name="Installation" href="installation.html"/> <item name="Configuration" href="configuration.html"/> <item name="FAQ" href="faq.html"/> </menu> ... </body> </project>
Menu items can also be nested. If you nest items, you will be
creating a collapsible menu in the left-hand navigation menu. The
following example adds a link "Developer Resources" which links to
/developer/index.html. When a user is looking at
the Developer Resources page, the menu items below the Developer
Resources menu item will be expanded.
Example 15.4. Adding a Link to the Site Menu
<project name="Sample Project"> ... <body> ... <menu name="Sample Project"> ... <item name="Developer Resources" href="/developer/index.html" collapse="true"> <item name="System Architecture" href="/developer/architecture.html"/> <item name="Embedder's Guide" href="/developer/embedding.html"/> </item> </menu> ... </body> </project>
When an item has the collapse attribute set to
true, Maven will collapse the item until a user is
viewing that specific page. In the previous example, when the user is
not looking at the Developer Resources page, Maven will not display the
System Architecture and Embedder's Guide links; instead, it will display
an arrow pointing to the Developer Resources link. When the user is
viewing the Developer Resources page it will show these links with an
arrow pointing down.
Maven places all site document under src/site.
Documents of similar format are placed in subdirectories of
src/site. All APT documents should
be in src/site/apt, all FML
documents should be in src/site/fml, and XDoc
documents should be in src/site/xdoc. The site
descriptor should be in src/site/site.xml, and all
resources should be stored under src/site/resources.
When the Maven Site plugin builds a web site, it will copy everything in
the resources directory to the root of the site. If you store an image in
src/site/resources/images/test.png, they you would
refer to the image from your site documentation using the relative path
images/test.png.
The following examples shows the location of all files in a project which contains APT, FML, HTML, XHTML, and some XDoc. Note that the XHTML content is simply stored in the resources directory. The architecture.html file will not be processed by Doxia, it will simply be copied to the output directory. You can use this approach if you want to include unprocessed HTML content and you don't want to take advantage of the templating and formatting capabilities of Doxia and the Maven Site plugin.
sample-project
+- src/
+- site/
+- apt/
| +- index.apt
| +- about.apt
| |
| +- developer/
| +- embedding.apt
|
+- fml/
| +- faq.fml
|
+- resources/
| +- images/
| | +- banner-left.png
| | +- banner-right.png
| |
| +- architecture.html
| +- jira-roadmap-export-2007-03-26.html
|
+- xdoc/
| +- xml-example.xml
|
+- site.xml
Note that the developer documentation is stored in
src/site/apt/developer/embedding.apt. This extra
directory below the apt directory will be reflected
in the location of the resulting HTML page on the site.
When the Site plugin renders the contents of the
src/site/apt directory it will produce
HTML output in directories relative to the site root.
If a file is in the apt directory it will be in the root directory of the
generated web site. If a file is in the apt/developer
directory it will be generated in the developer/
directory of the web site.
Maven uses a documentation-processing engine called Doxia which reads multiple source formats into a common document model. Doxia can then manipulate documents and render the result into several output formats, such as PDF or XHTML. To write document for your project, you will need to write your content in a format which can be parsed by Doxia. Doxia currently has support for Almost Plain Text (APT), XDoc (a Maven 1.x documentation format), XHTML, and FML (useful for FAQ documents) formats.
This chapter has a cursory introduction to the APT format. For a deeper understand of the APT format, or for an in-depth introduction to XDoc or FML, please see the following resources:
APT Reference: http://maven.apache.org/doxia/format.html
XDoc Reference: http://jakarta.apache.org/site/jakarta-site2.html
FML Reference: http://maven.apache.org/doxia/references/fml-format.html
Example 15.5, “APT Document” shows a simple APT document with an introductory paragraph and a simple list. Note that the list is terminated by the psuedo-element "[]".
Example 15.5. APT Document
---
Introduction to Sample Project
---
Brian Fox
---
26-Mar-2008
---
Welcome to Sample Project
This is a sample project, welcome! We're excited that you've decided to
read the index page of this Sample Project. We hope you enjoy the simple
sample project we've assembled for you.
Here are some useful links to get you started:
* {{{news.html}News}}
* {{{features.html}Features}}
* {{{faq.html}FAQ}}
[]
If the APT document from Example 15.5, “APT Document” were placed in
src/site/apt/index.apt, the Maven Site plugin will
parse the APT using Doxia and produce
XHTML content in
index.html.
Many projects maintain a Frequently Asked Questions (FAQ) page. Example 15.6, “FAQ Markup Language Document” shows an example of an FML document.
Example 15.6. FAQ Markup Language Document
<?xml version="1.0" encoding="UTF-8"?> <faqs title="Frequently Asked Questions"> <part id="General"> <faq id="sample-project-sucks"> <question>Sample project doesn't work. Why does sample project suck?</question> <answer> <p> We resent that question. Sample wasn't designed to work, it was designed to show you how to use Maven. If you really think this project sucks, then keep it to yourself. We're not interested in your pestering questions. </p> </answer> </faq> <faq id="sample-project-source"> <question>I want to put some code in Sample Project, how do I do this?</question> <answer> <p> If you want to add code to this project, just start putting Java source in src/main/java. If you want to put some source code in this FAQ, use the source element: </p> <source> for( int i = 0; i < 1234; i++ ) { // do something brilliant } </source> </answer> </faq> </part> </faqs>
Once your project's documentation has been written and you've
creates a site to be proud of, you will want to deploy it a server. To
deploy your site you'll use the Maven Site plugin which can take care of
deploying your project's site to a remote server using a number of methods
including FTP, SCP, and
DAV. To deploy the site using DAV,
configure the site entry of the distributionManagement
section in the POM, like this:
Example 15.7. Configuring Site Deployment
<project>
...
<distributionManagement>
<site>
<id>sample-project.website</id>
<url>dav:https://dav.sample.com/sites/sample-project</url>
</site>
</distributionManagement>
...
</project>
The url in distribution management has a leading
indicator dav which tells the Maven Site plugin to
deploy the site to a URL that is able to understand
WebDAV. Once you have added the
distributionManagement section to our
sample-project POM, we can try
deploying the site:
$ mvn clean site-deploy
If you have a server configured properly that can understand
WebDAV, Maven will deploy your project's web site to
the remote server. If you are deploying this project to a site and server
visible to the public, you are going to want to configure your web server
to access for credentials. If your web server asks for a username and
password (or other credentials, you can configure this values in your
~/.m2/settings.xml).
To configure a username/password combination for use during the
site deployment, we'll include the following in
$HOME/.m2/settings.xml:
Example 15.8. Storing Server Authentication in User-specific Settings
<settings>
...
<servers>
<server>
<id>sample-project.website</id>
<username>jdcasey</username>
<password>b@dp@ssw0rd</password>
</server>
...
</servers>
...
</settings>
The server authentication section can contain a number of
authentication elements. In the event you're using
SCP for deployment, you may wish to use public-key
authentication. To do this, specify the publicKey
and passphrase elements, instead of the password
element. You may still want to configure the username element, depending
on your server's configuration.
If you are working in a large group of developers, you'll want to
make sure that your web site's files end up with the proper user and
group permissions after they are published to the remote server. To
configure specific file and directory modes for use during the site
deployment, include the following in
$HOME/.m2/settings.xml:
Example 15.9. Configuring File and Directory Modes on Remote Servers
<settings>
...
<servers>
...
<server>
<id>hello-world.website</id>
...
<directoryPermissions>0775</directoryPermissions>
<filePermissions>0664</filePermissions>
</server>
</servers>
...
</settings>
The above settings will make any directories readable and writable by either the owner or members of the owner's primary group; the anonymous users will only have access to read and list the directory. Similarly, the owner or members of the owner's primary group will have access to read and write any files, with the rest of the world restricted to read-only access.
The default Maven template leaves much to be desired. If you wish to
customize your project's website beyond simply adding content,
navigational elements, and custom logos. Maven offers several mechanisms
for customizing your website that offer successively deeper access to
content decoration and website structure. For small, per-project tweaks,
providing a custom site.css is often enough. However,
if you want your customizations to be reusable across multiple projects,
or if your customizations involve changing the XHTML
that Maven generates, you should consider creating your own Maven website
skin.
The easiest way to affect the look and feel of your project's web
site is through the project's site.css. Just like
any images or XHTML content you provide for the
website, the site.css file goes in the
src/site/resources directory. Maven expects this
file to be in the src/site/resources/css
subdirectory. With CSS it is possible to change text
styling properties, layout properties, and even add background images
and custom bullet graphics. For example, if we decided that to make the
menu heading stand out a little more, we might try the following style
in src/site/resources/css/site.css:
#navcolumn h5 {
font-size: smaller;
border: 1px solid #aaaaaa;
background-color: #bbb;
margin-top: 7px;
margin-bottom: 2px;
padding-top: 2px;
padding-left: 2px;
color: #000;
}
When you regenerate the website, the menu headers should be framed
by a gray background and separated from the rest of the menu by some
extra margin space. Using this file, any structure in the
Maven-generated website can be decorated with custom
CSS. When you change site.css in
a specific Maven project, the changes will apply to that specific
project. If you are interested in making changes that will apply to more
than one Maven project, you can create a custom skin for the Maven Site
plugin.
There is no good reference for the structure of the default Maven site template. If you are attempting to customize the style of your Maven project, you should use a Firefox extension like Firebug as a tool to explore the DOM for your project's pages.
If the default Maven Site structure just doesn't do it for you, you can always customize the Maven site template. Customizing the Maven Site template gives you complete control over the ultimate output of the Maven plugin, and it is possible to customize your project's site template to the point where it hardly resembles the structure of a default Maven site template.
The Site plugin uses a rendering engine called Doxia, which in
turn uses a Velocity template to render the XHTML for
each page. To change the page structure that is rendered by default, we
can configure the site plugin in our POM to use a
custom page template. The site template is fairly complex, and you'll
need to have a good starting point for your customization. Start by
copying the default Velocity template from Doxia's Subversion repository
default-site.vm
to src/site/site.vm. This template is written in a
templating language called Velocity. Velocity is a simple templating
language which supports simple macro definition and allows you to access
an object's methods and properties using simple notation. A full
introduction is beyond the scope of this book, for more information
about Velocity and a full introduction please go to the Velocity project
site at http://velocity.apache.org.
The default-site.xml template is fairly
involved, but the change required to customize the left-hand menu is
relatively straightforward. If you are trying to change the appearance
of a menuItem, locate the menuItem
macro. It resides in a section that looks like this:
#macro ( menuItem $item ) ... #end
If you replace the macro definition with the macro definition listed below, you will injects Javascript references into each menu item which will allow the reader to expand or collapse the menu tree without suffering through a full page reload:
#macro ( menuItem $item $listCount )
#set ( $collapse = "none" )
#set ( $currentItemHref = $PathTool.calculateLink( $item.href,
$relativePath ) )
#set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
#if ( $item && $item.items && $item.items.size() > 0 )
#if ( $item.collapse == false )
#set ( $collapse = "collapsed" )
#else
## By default collapsed
#set ( $collapse = "collapsed" )
#end
#set ( $display = false )
#displayTree( $display $item )
#if ( $alignedFileName == $currentItemHref || $display )
#set ( $collapse = "expanded" )
#end
#end
<li class="$collapse">
#if ( $item.img )
#if ( ! ( $item.img.toLowerCase().startsWith("http") ||
$item.img.toLowerCase().startsWith("https") ) )
#set ( $src = $PathTool.calculateLink( $item.img, $relativePath ) )
#set ( $src = $item.img.replaceAll( "\\", "/" ) )
<img src="$src"/>
#else
<img src="$item.img" align="absbottom" style="border-width: 0"/>
#end
#end
#if ( $alignedFileName == $currentItemHref )
<strong>$item.name</strong>
#else
#if ( $item && $item.items && $item.items.size() > 0 )
<a onclick="expand('list$listCount')"
style="cursor:pointer">$item.name</a>
#else
<a href="$currentItemHref">$item.name</a>
#end
#end
#if ( $item && $item.items && $item.items.size() > 0 )
#if ( $collapse == "expanded" )
<ul id="list$listCount" style="display:block">
#else
<ul id="list$listCount" style="display:none">
#end
#foreach( $subitem in $item.items )
#set ( $listCounter = $listCounter + 1 )
#menuItem( $subitem $listCounter )
#end
</ul>
#end
</li>
#end
This change adds a new parameter to the
menuItem macro. For the new functionality to work,
you will need to change references to this macro, or the resulting
template may produce unwanted or internally inconsistent
XHTML. To finish changing these references, make a
similar replacement in the mainMenu macro. Find this
macro by looking for something similar to the following template
snippet:
#macro ( mainMenu $menus ) ... #end
Replace the mainMenu macro with the following implementation:
#macro ( mainMenu $menus )
#set ( $counter = 0 )
#set ( $listCounter = 0 )
#foreach( $menu in $menus )
#if ( $menu.name )
<h5 onclick="expand('menu$counter')">$menu.name</h5>
#end
<ul id="menu$counter" style="display:block">
#foreach( $item in $menu.items )
#menuItem( $item $listCounter )
#set ( $listCounter = $listCounter + 1 )
#end
</ul>
#set ( $counter = $counter + 1 )
#end
#end
This new mainMenu macro is compatible with the
new menuItem macro above, and also provides support
for a Javascript-enabled top-level menu. Clicking on a top-level menu
item with children will expand the menu and allow users to see the
entire tree without waiting for a page to load.
The change to the menuItem macro introduced an
expand() Javascript function. This method needs
to be added to the main XHTML template at the bottom
of this template file. Find the section that looks similar to the
following:
<head>
...
<meta http-equiv="Content-Type"
content="text/html; charset=${outputEncoding}" />
...
</head>
and replace it with this:
<head>
...
<meta http-equiv="Content-Type"
content="text/html; charset=${outputEncoding}" />
<script type="text/javascript">
function expand( item ) {
var expandIt = document.getElementById( item );
if( expandIt.style.display == "block" ) {
expandIt.style.display = "none";
expandIt.parentNode.className = "collapsed";
} else {
expandIt.style.display = "block";
expandIt.parentNode.className = "expanded";
}
}
</script>
#if ( $decoration.body.head )
#foreach( $item in $decoration.body.head.getChildren() )
#if ( $item.name == "script" )
$item.toUnescapedString()
#else
$item.toString()
#end
#end
#end
</head>
After modifying the default site template, you'll need to
configure your project's POM to reference this new
site template. To customize the site template, you'll need to use the
templateDirectory and template configuration
properties of the Maven Site plugin.
Example 15.10. Customizing the Page Template in a Project's POM
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<templateDirectory>src/site</templateDirectory>
<template>site.vm</template>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
Now, you should be able to regenerate your project website. When you do so you may notice that the resources and CSS for the maven site are missing. When a Maven project customizes the site template, the Site plugin expects the project to supply all of the default images and CSS. To seed your project's resources, you may want to copy the resources from the default Doxia site renderer project to your own project's resources directory by executing the following commands:
$ svn co \ http://svn.apache.org/repos/asf/maven/doxia/doxia-sitetools/\ trunk/doxia-site-renderer $ rm \ doxia-site-renderer/src/main/resources/org/apache/maven/\ doxia/siterenderer/resources/css/maven-theme.css $ cp -rf \ doxia-site-renderer/src/main/resources/org/apache/maven/\ doxia/siterenderer/resources/* \ sample-project/src/site/resources
Check out the doxia-site-renderer project,
remove the default maven-theme.css file and then
copy all the resources to your project's
src/site/resources directory.
When you regenerate the site, you'll notice that a few menu items
look like regular unstyled text. This is caused by a quirky interaction
between the site's CSS and our new custom page
template. It can be fixed by modifying our site.css
to restore the proper link color for these menus. Simply add
this:
li.collapsed, li.expanded, a:link {
color:#36a;
}
After regenerating the site, the menu's link color should be
corrected. If you applied the new site template to the same
sample-project from this chapter, you'll notice that the menu now
consists of a tree. Clicking on "Developer Resources" no longer takes
you to the "Developer Resources" page; in stead, it expands the
sub-menu. Since you've turned the Developer Resources menu-item into a
dynamically-folding sub-menu, you have lost the ability to reach the
developer/index.apt page. To address this change,
you should add an Overview link to the sub-menu which references the
same page:
Example 15.11. Adding a Menu Item to a Site Descriptor
<project name="Hello World"> ... <menu name="Main Menu"> ... <item name="Developer Resources" collapse="true"> <item name="Overview" href="/developer/index.html"/> <item name="System Architecture" href="/developer/architecture.html"/> <item name="Embedder's Guide" href="/developer/embedding.html"/> </item> </menu> ... </project>
If your organization is created many Maven project sites, you will likely want to reuse site template and CSS customizations throughout an organization. If you want thirty projects to share the same CSS and site template, you can use Maven's support for skinning. Maven Site skins allow you to package up resources and templates which can be reused by other projects in lieu of duplicating your site template for each project which needs to be customized.
While you can define your own skin, you may want to consider using one of Maven's alternate skins. You can choose from several skins. These each provide their own layout for navigation, content, logos, and templates:
Maven Classic Skin -
org.apache.maven.skins:maven-classic-skin:1.0
Maven Default Skin -
org.apache.maven.skins:maven-default-skin:1.0
Maven Stylus Skin - org.apache.maven.skins:maven-stylus-skin:1.0.1
You can find an up-to-date and comprehensive listing in the Maven repository: http://repo1.maven.org/maven2/org/apache/maven/skins/.
Creating a custom skin is a simple matter of wrapping your
customized maven-theme.css in a Maven project, so
that it can be referenced by groupId,
artifactId, and version. It can
also include resources such as images, and a replacement website
template (written in Velocity) that can generate a completely different
XHTML page structure. In most cases, custom
CSS can manage the changes you desire. To
demonstrate, let's create a designer skin for the sample-project
project, starting with a custom
maven-theme.css.
Before we can start writing our custom CSS, we
need to create a separate Maven project to allow the
sample-project site descriptor to reference it.
First, use Maven's archetype plugin to create a basic project. Issue the
following command from the directory above the
sample-project project's root directory:
$ mvn archetype:create -DartifactId=sample-site-skin
-DgroupId=com.sonatyp.maven
This will create a project (and a directory) called
sample-site-skin. Change directories to the new
sample-site-skin directory, remove all of the source
code and tests, and create a directory to store your skin's
resources:
$ cd sample-site-skin $ rm -rf src/main/java src/test $ mkdir src/main/resources
Next, write a custom CSS for the custom skin. A
Å file in a Maven site skin should be placed in
src/main/resources/css/maven-theme.css. Unlike the
site.css file, which goes in the site-specific
source directory for a project, the maven-theme.css
will be bundled in a JAR artifact in your local Maven
repository. In order for the maven-theme.css file to be included in the
skin's JAR file, it must reside in the main
project-resources directory,
src/main/resources.
As with the default the default site template, you will want to
start customizing your new skin's CSS from a good
starting point. Copy the CSS file used by the default
Maven skin to your project's maven-theme.css. To
get a copy of this theme file, save the contents of maven-theme.css
from the maven-default-skin project to
src/main/resources/css/maven-theme.css in our new
skin project.
Now that we have the base theme file in place, customize it using
the CSS from our old site.css file. Replace the
#navcolumn h5 CSS block with the
following:
#navcolumn h5 {
font-size: smaller;
border: 1px solid #aaaaaa;
background-color: #bbb;
margin-top: 7px;
margin-bottom: 2px;
padding-top: 2px;
padding-left: 2px;
color: #000;
}
Once you've customized the maven-theme.css,
build and install the sample-site-skin
JAR artifact to your local Maven repository by
running:
$ mvn clean install
Once the installation is complete, switch back to the
sample-project project directory, if you already
customized the site.css earlier in this chapter,
move site.css to site.css.bak
so it no longer affects the output of the Maven Site plugin:
$ mv src/site/resources/css/site.css src/site/resources/css/site.css.bak
To use the sample-site-skin in the
sample-project site, you'll need to add a reference
to the sample-site-skin artifact in the
sample-project's site descriptor. A site references a
skin in the site descriptor using the skin element:
Example 15.12. Configuring a Custom Site Skin in Site Descriptor
<project name="Sample Project"> ... <skin> <groupId>com.sonatype.maven</groupId> <artifactId>sample-site-skin</artifactId> </skin> ... </project>
You can think of a Maven Site skin as a site dependency. Site skins are referenced as artifacts with a groupId and an artifactId. Using a site skin allows you to consolidate site customizations to a single project, and makes reusing custom CSS and site templates as easy as reusing build logic through a custom Maven plugin.
Just as you can customize a the site CSS in a
Maven Site skin, you can also customize the site template. Doxia's
site-rendering tools will expect to find a file called
META-INF/maven/site.vm inside the skin
JAR. To incorporate a custom page template, copy the
template file into the correct location within the
sample-site-skin. Copy the custom site template
developed earlier in the chapter to
src/main/resources/META-INF/maven in
sample-site-skin:
$ mv sample-project/src/site/site.vm \
sample-site-skin/src/main/resources/META-INF/maven
If you already customized the site template in
sample-project, remove the Site plugin configuration
which pointed to this site template. The Site plugin will render the
site using the site template referenced in the site skin.
<plugin>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<templateDirectory>src/site</templateDirectory>
<template>site.vm</template>
</configuration>
</plugin>
A Maven Site skin is expected to include all of the resources it
depends on. This includes CSS, images, and logos. If
you already customized the site template earlier in the chapter, you've
already copied the default doxia-site-renderer
resources to the sample-project's
src/site/resources directory. You'll need to move
those files out of the sample-project project and
into the new sample-site-skin project by executing
the following commands:
$ cd ..
$ mkdir -p sample-site-skin/src/main/resources/css
$ mv sample-project/src/site/resources/css/maven-base.css \
sample-site-skin/src/main/resources/css
$ mkdir -p sample-site-skin/src/main/resources/images
$ mv sample-project/src/site/resources/images/logos \
sample-site-skin/src/main/resources/images
$ mv sample-project/src/site/resources/images/expanded.gif \
sample-site-skin/src/main/resources/images
$ mv sample/src/site/resources/images/collapsed.gif \
sample-site-skin/src/main/resources/images
You've changed the sample-site-skin, so you'll
need to install this skin into your local Maven repository. Once you
install the skin locally and rebuild the
sample-project web site. You'll see that the skin's
custom site template was applied to the
sample-project's web site. You'll notice that the
color of the menu items may be a little off because you haven't added
the necessary CSS to the collapsed and expanded menu
items. To do this, modify
src/main/resources/css/maven-theme.css.
Change:
a:link {
...
}
to this:
li.collapsed, li.expanded, a:link {
...
}
Rebuild the skin, then regenerate the website, and you'll see that the menu items have returned to normal. You've successfully created a Maven theme which can be used to apply CSS and templates to a set of projects.
This section lists some useful tips and tricks you can use when creating a Maven site.
To inject XHTML into the
HEAD element, add a head element to the body element
in your project's Site descriptor. The following example adds a feed
link to every page in the sample-project web
site.
Example 15.13. Injecting HTML into the HEAD element
<project name="Hello World"> ... <body> <head> <link href="http://sample.com/sites/sample-project/feeds/blog" type="application/atom+xml" id="auto-discovery" rel="alternate" title="Sample Project Blog" /> </head> ... </body> </project>
If you are working on a project which is being developed by an organization, you may want to add links under your project's logo. Assume that your project is a part of the Apache Software Foundation, you might want to add a link to the Apache Software Foundation web site right below your logo, and you might want to add a link to a parent project as well. To add links below your site logo, just add a links element to the body element in the Site descriptor. Each item element in the links element will be rendered as a link in a bar directly below your project's logo. The following example would add a link to the Apache Software Foundation followed by a link to the Apache Maven project.
Example 15.14. Adding Links Under Your Site Logo
<project name="Hello World"> ... <body> ... <links> <item name="Apache" href="http://www.apache.org"/> <item name="Maven" href="http://maven.apache.org"/> </links> ... </body> </project>
If your hierarchy exists within a logical hierarchy, you may want
to place a series of breadcrumbs to give the user a sense of context and
give them a way to navigate up the tree to projects which might contain
the current project as a subproject. To configure breadcrumbs, add a
breadcrumbs element to the body
element in the site descriptor. Each item element
will render a link, and the items in the breadcrumbs
element will be rendered in order. The breadcrumb items should be listed
from highest level to lowest level. In the following site descriptor,
the Codehaus item would be seen to contain the Mojo item.
Example 15.15. Configuring the Site's Breadcrumbs
<project name="Sample Project"> ... <body> ... <breadcrumbs> <item name="Codehaus" href="http://www.codehaus.org"/> <item name="Mojo" href="http://mojo.codehaus.org"/> </breadcrumbs> ... </body> </project>
When you are documenting a project that has multiple versions, it
is often very helpful to list the project's version number on every
page. To display your project's version on the website, simply add the
version element to your site descriptor:
Example 15.16. Positioning the Version Information
<project name="Sample Project"> ... <version position="left"/> ... </project>
This will position the version (in the case of the sample-project project, it will say "Version: 1.0-SNAPSHOT") in the upper left-hand corner of the site, right next to the default "Last Published" date. Valid positions for the project version are:
Left side of the bar just below the site logo
Right side of the bar just below the site logo
Top of the menu
Bottom of the menu
Suppress the version entirely
In some cases, you may wish to reformat or reposition the "Last Published" date for your project website. Just like the project version tip above, you can specify the position of the publication date by using one of the following:
Left side of the bar just below the site logo
Right side of the bar just below the site logo
Top of the menu
Bottom of the menu
Suppress the publication entirely
Example 15.17. Positioning the Publish Date
<project name="Sample Project"> ... <publishDate position="navigation-bottom"/> ... </project>
By default, the publication date will be formatted using the date
format string MM/dd/yyyy. You can change this format
by using the standard notation found in the JavaDocs for
java.text.SimpleDateFormat (see JavaDoc for
SimpleDateFormat
for more information). To reformat the date using
yyyy-MM-dd, use the following
publishDate element.
Example 15.18. Configuring the Publish Date Format
<project name="Sample Project"> ... <publishDate position="navigation-bottom" format="yyyy-MM-dd"/> ... </project>
In addition to its advanced document rendering features, Doxia also provides a macro engine that allows each input format to trigger injection of dynamic content. An excellent example of this is the snippet macro, which allows a document to pull a code snippet out of a source file that's available via HTTP. Using this macro, a small fragment of APT can be rendered into XHTML. The following APT code calls out to the snippet macro. Please note that this code should be on a single continuous line, the black slash character is inserted to denote a line break so that this code will fit on the printed page.
%{snippet|id=modello-model|url=http://svn.apache.org/repos/asf/maven/\
archetype/trunk/maven-archetype/maven-archetype-model/src/main/\
mdo/archetype.mdo}
Example 15.19. Output of the Snippet Macro in XHTML
<div class="source"><pre> <model> <id>archetype</id> <name>Archetype</name> <description><![CDATA[Maven's model for the archetype descriptor. ]]></description> <defaults> <default> <key>package</key> <value>org.apache.maven.archetype.model</value> </default> </defaults> <classes> <class rootElement="true" xml.tagName="archetype"> <name>ArchetypeModel</name> <description>Describes the assembly layout and packaging.</description> <version>1.0.0</version> <fields> <field> <name>id</name> <version>1.0.0</version> <required>true</required> <type>String</type> </field> ... </fields> </class> </classes> </model> </pre></div>
Doxia macros MUST NOT be indented in APT source documents. Doing so will result in the APT parser skipping the macro altogether.
For more information about defining snippets in your code for reference by the snippet macro, see the Guide to the Snippet Macro on the Maven website, at http://maven.apache.org/guides/mini/guide-snippet-macro.html.
