ftw.pdfgenerator

A library for generating PDF representations of Plone objects with LaTeX.


Keywords
ftw, pdf, generator
License
GPL-2.0
Install
pip install ftw.pdfgenerator==1.6.10

Documentation

Introduction

ftw.pdfgenerator is meant to be used for generating PDFs from structured data using predefined LaTeX views. It is not useful for converting full HTML pages into LaTeX / PDFs, although it is able to convert small HTML chunks into LaTeX.

http://onegov.ch/approved.png/image

Certified: 01/2013

Requirements

ftw.pdfgenerator requires a TeX distribution with a pdflatex executable to be installed.

These TeX distributions are recommended:

The package is compatible with Plone 4.3 and 5.1.

Installing

Add ftw.pdfgenerator to your buildout configuration:

[instance]
eggs =
  ftw.pdfgenerator

Usage

The pdfgenerator uses LaTeX for generating the PDF. You need to provide a layout and a view for your context for being able to create a PDF.

Real world examples

Some packages using ftw.pdfgenerator:

Defining a layout

A layout is a multi adapter addapting context, request, builder. You can easily define a new layout using the mako templating engine (example: layout.py):

>>> from example.conference.session import ISession
>>> from ftw.pdfgenerator.interfaces import IBuilder
>>> from ftw.pdfgenerator.interfaces import ICustomizableLayout
>>> from ftw.pdfgenerator.layout.customizable import CustomizableLayout
>>> from zope.component import adapts
>>> from zope.interface import Interface
>>> from zope.interface import implements

>>> class SessionLayout(MakoLayoutBase):
...     adapts(ISession, Interface, IBuilder)
...     implements(ICustomizableLayout)
...
...     template_directories = ['session_templates']
...     template_name = 'layout.tex'
...
...     def before_render_hook(self):
...         self.use_babel()
...         self.use_package('inputenc', options='utf8')
...         self.use_package('fontenc', options='T1')

Register the layout with zcml (example: configure.zcml):

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser">

    <adapter factory=".layout.SessionLayout"
             provides="ftw.pdfgenerator.interfaces.ILaTeXLayout" />

</configure>

Create a template as defined in SessionLayout.template_name (example: session_templates/layout.tex):

<%block name="documentclass">
\documentclass[a4paper,10pt]{article}
</%block>

<%block name="usePackages">
  ${packages}
</%block>

<%block name="beneathPackages">
</%block>


<%block name="aboveDocument">
</%block>

\begin{document}

<%block name="documentTop">
  % if logo:
    ${logo}
  % endif
</%block>

${content}

<%block name="documentBottom">
</%block>

\end{document}

There are more methods on the layout, see the definition in ftw.pdfgenerator.interfaces.ILaTeXLayout.

Defining a LaTeX view

For every context for which a PDF is generated a LaTeX view (ILaTeXView) is rendered. The view is a multi adapter adapting context, request, layout. There is a view based on the mako templating engine which can be extended (example: views.py):

>>> from example.conference.session import ISession
>>> from ftw.pdfgenerator.interfaces import ILaTeXLayout
>>> from ftw.pdfgenerator.interfaces import ILaTeXView
>>> from ftw.pdfgenerator.view import MakoLaTeXView
>>> from zope.component import adapts
>>> from zope.interface import Interface
>>> from zope.interface import implements

>>> class SessionLaTeXView(MakoLaTeXView):
...     adapts(ISession, Interface, ILaTeXLayout)
...     implements(ILaTeXView)
...
...     template_directories = ['session_templates']
...     template_name = 'view.tex'
...
...     def get_render_arguments(self):
...         return {'title': self.convert(self.context.Title()),
...                 'description': self.convert(self.context.description),
...                 'details': self.convert(self.context.details)}

Register the view with zcml (example: configure.zcml):

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser">

    <adapter factory=".views.SessionLaTeXView"
             provides="ftw.pdfgenerator.interfaces.ILaTeXView" />

</configure>

Create a template with the name defined in the class (example: session_templates/view.tex):

\section*{${title}}
% if description:
  \small ${description}
% endif
\normalsize ${details}

Generating a PDF

When a layout and a view for the context are registered the PDF can be generated by simply calling the view @@export_pdf on the context.

Recursive views

When extending from ftw.pdfgenerator.view.RecursiveLaTeXView and inserting the variable latex_content in your template, the view automatically renders all children for which a ILaTeXView is found.

HTML to LaTeX conversion

ftw.pdfgenerator comes with a simple but powerful HTML to LaTeX converter which is optimized for the common WYSIWYG-Editors used in Plone.

The converter can be used:

  • in views, using self.convert(html)
  • in layouts, using self.get_converter().convert(html)

It uses regular expressions for the simple conversions and python subconverters for the more complicated conversions. The converter is heavily customizable.

Custom subconverters

Footnote

Generate a footnote by wrapping any text in a span with the class footnote. Specify the footnote text in the data-footnote attribute. Example:

<span class="footnote" data-footnote="text in footnote">text on the page</span>

Customizable layouts

When using multiple, independent addon packages using ftw.pdfgenerator, every package may implement a new, specific layout. This can be painful if there is a need to customize all layouts and add a logo image for example.

For making this easier all customizable layouts can be customized with one single adapter. This only works for layouts subclassing ftw.pdfgenerator.layout.customizable.CustomizableLayout. Those layouts need to follow certain concepts and provide inheritable blocks in the mako template. Ensure you follow the standards by subclassing and running the tests from ftw.pdfgenerator.tests.test_customizable_layout.TestCustomizableLayout.

Implementing customization adapter is very simple when customizable layouts are used. For example we change the logo image (assume the logo is at custom/mylogo.png):

>>> from ftw.pdfgenerator.customization import LayoutCustomization
>>> from ftw.pdfgenerator.interfaces import ILayoutCustomization
>>> from zope.interface import implements
>>>
>>> class MyCustomization(LayoutCustomization):
...     implements(ILayoutCustomization)
...
...     template_directories = ['custom']
...     template_name = 'layout_customization.tex'
...
...     def before_render_hook(self):
...         self.add_raw_template_file('mylogo.png')
...         self.layout.use_package('graphicx')
...
...     def get_render_arguments(self, args):
...         args['logo'] = r'\includegraphics{mylogo.png}'
...         return args

It is also possible to change the template and fill predefined slots (example: custom/layout_customization.tex):

<%inherit file="original_layout" />
<%block name="documentTop">
  my branding
</%block>

The layout customization adapter adapts context, request and the original layout.

Tables

ftw.pdfgenerator is able to convert HTML-Tables to LaTeX. Since HTML and LaTeX have completely different presentation concepts the convertion is limitted.

For getting the best results theese rules should be followed:

  • Define the width of every column. The table will be streched to the text width in the defined proportions. Without defining the widths LaTeX is unable to insert newlines dynamically.
  • Use relative widths (%).
  • Define table headings using <thead> for long tables which may be splitted over multiple pages.

CSS classes:

page-break (<table>)
Force the longtable environment, allowing LaTeX to split up the table over multiple pages.
no-page-break (<table>)
Force the tabular environment, prohibiting LaTeX from splitting the table up over multiple pages. If the table is longer than the page it is truncated - content may be missing in this case.
border-grid / listing (<table>)
Display the table in a grid: every cell has a border on every side.
notListed (<table>)
When using a <caption>, do not list the table in the list of tables.
border-left (<td>, <th>)
Display a border on the left side of the cell.
border-right (<td>, <th>)
Display a border on the right side of the cell.
border-top (<td>, <th>)
Display a border on the top side of the cell.
border-bottom (<td>, <th>)
Display a border on the bottom side of the cell.
right (<td>, <th>)
Right align the content of the cell.
left (<td>, <th>)
Left align the content of the cell.
center (<td>, <th>)
Center the content of the cell.
indent2 (<td>, <th>)
Indent the content by 0.2 cm.
indent10 (<td>, <th>)
Indent the content by 1 cm.
bold (<td>, <th>)
Display cell contents in bold font.
grey (<td>, <th>)
Display cell content with grey text color.
footnotesize (<td>, <th>)
Display cell content with smaller font size (\footnotesize).
scriptsize (<td>, <th>)
Display cell content with smaller font size (\scriptsize).

Links

Copyright

This package is copyright by 4teamwork.

ftw.pdfgenerator is licensed under GNU General Public License, version 2.