Fork me on GitHub

HST PDF Renderer

Dependencies

Add the following dependency to the SITE Application module POM:

    <!-- SNIP -->

    <repository>
      <id>hippo-maven2-forge</id>
      <name>Hippo Maven 2 Forge repository</name>
      <url>http://maven.onehippo.com/maven2-forge/</url>
      <snapshots />
    </repository>

    <!-- SNIP -->

    <dependency>
      <groupId>org.onehippo.forge.hstpdfrenderer</groupId>
      <artifactId>hstpdfrenderer</artifactId>
      <version>${forge.hstpdfrenderer.version}</version>
    </dependency>

    <!-- SNIP -->
        

Servlet Filter Configuration

Add the servlet filter configuration in the web.xml of your web application like the following:

Note: The mapping of the servlet filter, 'HtmlPDFRenderingFilter', must be located before the other rendering servlet filters such as 'HstFilter' because 'HtmlPDFRenderingFilter' should capture the rendered HTML output to transform to PDF output.

In the following example configuration, the HtmlPDFRenderingFilter servlet filter is configured to handle all the request paths starting with '/pdf/*'. This example assumes you will configure a HST mount named 'pdf' under the HST root mount for convenience.

  <!-- SNIP -->

  <filter>
    <filter-name>HtmlPDFRenderingFilter</filter-name>
    <filter-class>org.onehippo.forge.hst.pdf.renderer.servlet.HtmlPDFRenderingFilter</filter-class>
    <init-param>
      <param-name>tidy.props</param-name>
      <param-value>/WEB-INF/tidy.properties</param-value>
    </init-param>
    <init-param>
      <param-name>css.uris</param-name>
      <param-value>/WEB-INF/default-pdf-renderer.css</param-value>
    </init-param>
    <!--
    <init-param>
      <param-name>font.paths</param-name>
      <param-value>
        /home/tester/fonts/courier.ttf
        /home/tester/fonts/verdana.ttf
      </param-value>
    </init-param>
    -->
  </filter>

  <!-- SNIP -->

  <filter-mapping>
    <filter-name>HtmlPDFRenderingFilter</filter-name>
    <url-pattern>/pdf/*</url-pattern>
  </filter-mapping>

  <!-- SNIP -->
        

Here is the detail for all the configurable init parameters of HtmlPDFRenderingFilter:

Init Parameter Name Description Example Value(s) Default Value Since
tidy.props Context relative JTidy configuration properties resource path.
The properties file should contain valid JTidy configurations.
For detail on available JTidy configurations, see http://tidy.sourceforge.net/docs/quickref.html.
/WEB-INF/tidy.properties 1.01.00
css.uris CSS file resource paths used when generating PDF output. You can specify multiple CSS file resources by separating comma, semicolon, tab or line break. Each CSS file resource can be either context relative path (e.g., /WEB-INF/default-pdf-renderer.css) or file: URI or relative path from the current working directory. /WEB-INF/default-pdf-renderer.css 0.01.00
font.paths Font file paths used when embedding fonts into PDF output. You can specify multiple Font file paths by separating comma, semicolon, tab or line break. Each font file must be absolute file path (e.g., /home/tester/fonts/courier.ttf). /home/tester/fonts/courier.ttf 0.01.00
buffer.size Byte buffer size used when cleaning up HTML output and transforming HTML output to XHTML output internally. 4096 4096 0.01.00
user.agent.callback.class The name of a custom class which implements org.xhtmlrenderer.extend.UserAgentCallback. If you want to customize the internal callback mechanism for Flying Saucer for some reason (e.g., custom image loading), then you can provide the class name of your custom class. 0.01.00

Example: Add 'pdf' Mount in HST Configuration

As mentioned above, it is very convenient if you configure a sub mount for automatic PDF generation from the normal HTML rendering because the servlet filter configuration and link generations become much easier.

So, for example, 'pdf' sub mount can be configured under 'hst:root' mount:

      <!-- SNIP -->

      <sv:node sv:name="hst:root">
        <sv:property sv:name="jcr:primaryType" sv:type="Name">
          <sv:value>hst:mount</sv:value>
        </sv:property>

        <!-- SNIP -->

        <!-- The following 'pdf' mount configuration is added under 'hst:root' mount configuration. -->
        <sv:node sv:name="pdf">
          <sv:property sv:name="jcr:primaryType" sv:type="Name">
            <sv:value>hst:mount</sv:value>
          </sv:property>
          <sv:property sv:name="hst:alias" sv:type="String">
            <sv:value>pdf</sv:value>
          </sv:property>
        </sv:node>
      </sv:node>

      <!-- SNIP -->
        

You can also consider configuring sitemap items for automatic PDF generation URLs, but in that case, you will have to configure many more URL patterns for HtmlPDFRenderingFilter and it will more difficult or tedious to generate PDF URL links.

Example: Create a 'pdf' link in your page(s)

If you configured a pdf rendering mount, then it is very easy to generate PDF rendering links in your templates. See the following example:

    <c:if test="${not empty document}">
      <div id="pdflink">
        <a href='<hst:link mount="pdf" hippobean="${document}"/>'>
          <img src="<hst:link path="/images/pdf.gif"/>" border="0" />
        </a>
      </div>
    </c:if>
        

Example: Stylesheet(s) for PDF Rendering

HtmlPDFRenderingFilter uses the configured stylesheet resources when rendering PDF output. Here's an example CSS file (You can download this example here.):

@page { 
  size: letter;
  margin: 0.8in; 
  -fs-flow-top: "header";
  -fs-flow-bottom: "footer";
  -fs-flow-left: "left";
  -fs-flow-right: "right";
  border: thin solid gray;
  padding: 1em;
  @top-left {
    content: "Generated PDF Pages";
  }
  @top-right {
    content: "HST PDF Renderer";
  }
  @bottom-left {
    content: "www.onehippo.org";
  }
  @bottom-right {
    content: "Page " counter(page) "/" counter(pages);
  }
}

#header {
  font: bold serif;
  position: absolute; top: 0; left: 0; 
  -fs-move-to-flow: "header";
}

#footer {
  font-size: 90%; font-style: italic; 
  position: absolute; top: 0; left: 0;
  -fs-move-to-flow: "footer";
}

#pagenumber:before {
  content: counter(page); 
}

#pagecount:before {
  content: counter(pages);  
}

#pagebreakbefore {
  page-break-before: always;
}

#pagebreakafter {
  page-break-after: always;
}

#hd {
  display: none;
}

#leftmenu {
  display: none;
}

#right {
  display: none;
}
        

See the The Flying Saucer User's Guide for detail.