如果默认的Maven站点结构不符合你的要求,你可以自定义Maven站点模板。自定义该模板让你完全控制Maven Site插件的最终输出,也能让你使用非默认的目录结构。
Site插件使用了叫做Doxia的渲染引擎,而它实际上使用Velocity模板将页面渲染成XHTML。要更改默认被渲染的页面结构,我们可以在POM中配置site插件使用自定义的页面模板。site模板相当复杂,你需要有一个关于自定义配置的良好起点。一开始从Doxia的Subversion仓库default-site.vm复制默认的Velocity模板至src/site/site.vm
。该模板使用Velocity模板语言编写。Velocity是一个简单的模板语言,它支持简单的宏定义,允许你使用简单标记访问对象的方法和属性。全面的介绍超出了本书的范围,要了解更多的关于Velocity的信息级全面介绍,访问Velocity的项目站点http://velocity.apache.org。
default-site.xml
模板相当复杂,但自定义左边导航菜单相对的比较简单。如果你试图更改一个menuItem
的外观,找到menuItem
宏。它位于一个如下的小节中:
#macro ( menuItem $item ) ... #end
如果你使用如下的宏定义替换了默认的宏定义,你将为每个菜单项嵌入Javascript引用,能让用户在不用重新载入整个页面的情况下展开或收缩菜单树。
#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
该更改为menuItem
宏添加了一个新的参数。为了使新功能正确工作,你需要更改所有对于该宏的引用,否则最终的模板可能会生成非预期的或者不一致的XHTML。要完成这些引用的更改,在mainMenu
宏中进行一次替换。寻找类似下面模板片段的代码,以找到该宏。
#macro ( mainMenu $menus ) ... #end
使用如下的实现替换mainMenu
宏。
#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
这个新的mainMenu
宏现在和前面的menuItem
宏匹配了,同时也为顶层的菜单提供了Javascript支持。点击带有子项的顶层菜单,会得到展开的菜单,能让用户在不用等待页面重新载入的情况下查看整个树。
对于menuItem
宏的更改引入了一个expand()
Javascript函数。该方法需要被加入到模板文件底部的主XHTML模板中。找到类似于下面的代码片段:
<head> ... <meta http-equiv="Content-Type" content="text/html; charset=${outputEncoding}" /> ... </head>
然后进行如下的替换:
<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>
在修改了默认站点模板之后,你需要配置项目POM以引用这个新的站点模板。为此,你需要使用Maven
Site插件的templateDirectory
和template
配置属性。
Example 15.10. 在一个项目的POM中自定义页面模板
<project> ... <build> <plugins> <plugin> <artifactId>maven-site-plugin</artifactId> <configuration> <templateDirectory>src/site</templateDirectory> <template>site.vm</template> </configuration> </plugin> </plugins> </build> ... </project>
现在,你应该能够重新生成你项目的web站点了。这时你可能会注意到maven站点的资源和CSS丢失了。当一个Maven项目自定义站点模板的时候,Site插件认为该项目会提供所有默认的图片和CSS。为了提供项目的资源,你可以从默认的Doxia站点渲染项目中复制资源到你项目的资源目录中,运行如下命令:
$ 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
签出doxia-site-renderer
项目,删除默认的maven-theme.css
文件,然后复制所有的资源到你的src/site/resources
目录。
当你重新生成站点的时候,你会注意到一些菜单项看起来像常规未修饰的文本。这是因为站点CSS和新的自定义页面模板发生了一些诡异的交互。修改site.css
,为菜单恢复正确的链接颜色后便可修复。只要添加如下配置:
li.collapsed, li.expanded, a:link { color:#36a; }
在重新生成站点之后,菜单的链接颜色看起来正确了。如果你将这个新的站点模板应用到本章的sample-project项目中,你会看到菜单现在包含了一棵树。点击“Developer
Resources”不会再打开“Developer Resources”页面;取而代之的,是展开子菜单。由于你将Developer
Resources转换成了一个动态折叠的子菜单,你不再可以通过该菜单打开developer/index.apt
页面。为了对付这种变化,你可以在该子菜单下添加一个Overview链接,指向同样的页面:
Example 15.11. 给站点描述符添加一个菜单项
<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>