Simple XDV theming setup¶
A bit of background¶
“Deliverance” or xdv is something that I’ve been using for a while. It started in 2007 when hearing a presentation at a Plone sprint.
Basically, you have three parts:
The actual website(s) you want to theme.
A html file with the layout you want to have.
A rules file that tells xdv/deliverance which items to take from the source website and where to place them in the layout.
I’ve got two websites (a plone one for my church and a sphinx + plain html one that’s reinout.vanrees.org) that use deliverance/xdv
The Plone one uses an older xdv version that I hooked up in a PasteScript
.inifile.My own website uses an old branch I once made of deliverance with some custom fixes. That deliverance version can be run on its own (with a cronjob to start it when the server starts).
It is all a bit brittle, somehow. It all runs perfectly, mind you, but I don’t dare touching it. So many moving parts and small differences. And nagging doubts about the small things that went wrong when deploying it.
Time for a fresh start¶
Time for a fresh start. I really like the xdv-idea and I had a website that was just perfect for xdv. I recently started generating documentation for all our products and started putting it online at http://doc.lizardsystem.nl . There are a couple of different kinds of pages in there:
Plain generated html index pages.
The
python setup.py --long-descriptionoutput, rendered as html. Basically the same you’d get when releasing a python package on pypi.Coverage output.
Planned, but not there yet: sphinx documentation. Two packages already have it, but I just haven’t hooked it up in the automatic process.
Problem: I’m not going to make a nice sphinx layout and a regular html page layout and, yep, another long-description layout. The layout isn’t the problem, but you have to hook it up into at least three different documentation generation steps.
Solution: xdv. Just make one layout and write up a decent rule file that copy/pastes the correct bits and pieces out of the various source formats into the layout’s proper elements.
Current setup¶
Googling and reading my way through various websites, I settled for the following setup.
XDV, not deliverance. Xdv is a simpler, smaller version of deliverance and I don’t need the big version. And xdv has the interest and manpower of Plone behind it, so that’s solid. (Warning: they’re renaming it to diazo at the moment…)
dv.xdvserver as a piece of wsgi middleware for actually applying the xdv transformation.
collective.recipe.modwsgi to easily set up that wsgi middleware and to get an wsgi script I can feed to apache.
What I added to my setup.py install_requires list:
...
'PasteDeploy',
'PasteScript',
'dv.xdvserver', # This pulls in xdv itself, btw.
...
In my buildout.cfg, I added two parts:
[wsgiapp]
# Generate a script that's a wsgi script that runs the
# paste.ini config file.
recipe = collective.recipe.modwsgi
eggs = ${buildout:eggs}
config-file = ${buildout:directory}/etc/paste.ini
[wsgiconf]
# Generate the paste.ini config file with the wsgi config.
# collective.recipe.template makes sure all the absolute
# paths are correct.
recipe = collective.recipe.template
input = ${buildout:directory}/etc/paste.ini.in
output = ${buildout:directory}/etc/paste.ini
The wsgi configuration file paste.ini looks like this. Irritating is that
you have to specify a full logging setup at the end: otherwise it won’t
start (that’s because collective.recipe.modwsgi requires it):
[composite:main]
# Main url mapper, this is the actual start of the site.
# This section tells paster to serve everything in /static
# with [app:theme_resources] and the rest with [app:root].
use = egg:Paste#urlmap
/static = theme_resources
/ = root
[app:theme_resources]
# Serve everything in /theme from the static directory.
use = egg:Paste#static
document_root = /home/reinout/buildout/doc/theme/static
[app:root]
# Likewise, our actual content (coverage, long-description,
# sphinx) is in var/www/. Just serve it as static files,
# but first run it through our actual xdv filter.
use = egg:Paste#static
document_root = /home/reinout/buildout/doc/var/www
filter-with = xdv
[filter:xdv]
# The actual xdv filter which is the purpose of this entire
# file! Give it a ruleset (=configuration) and our base
# theme .html file.
use = egg:dv.xdvserver#xdv
theme = /home/reinout/buildout/doc/theme/index.html
rules = /home/reinout/buildout/doc/theme/rules.xml
# live=true means changes to the rules or theme are applied
# instantly, otherwise you'd need to restart apache.
# There's a bit of perfomance hit, of course.
live = true
[server:main]
# Development server, call it with
# "bin/paster server etc/paste.ini".
use = egg:Paste#http
host = 127.0.0.1
port = 8000
# Mandatory logging config below, otherwise
# collective.recipe.modwsgi refuses to work.
[loggers]
keys = root
[handlers]
keys = logfile
[formatters]
keys = logfile
[logger_root]
level = INFO
handlers = logfile
[handler_logfile]
class=logging.FileHandler
args=('/home/reinout/buildout/doc/var/log/xdv.log',)
level=INFO
formatter=logfile
[formatter_logfile]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt = %H:%M:%S
And our rules.xml file with - for the moment- just a couple of very basic
transformations:
<rules xmlns="http://namespaces.plone.org/xdv"
xmlns:css="http://namespaces.plone.org/xdv+css">
<!-- Note: these prepend/append parts use the "old"
xpath selectors. I can change them to css selectors
later on. -->
<prepend theme="//head" content="//head/base"
nocontent="ignore" />
<prepend theme="//head" content="//head/link"
nocontent="ignore" />
<prepend theme="//head" content="//head/style"
nocontent="ignore" />
<append theme="//head" content="//head/script"
nocontent="ignore" />
<append theme="//head" content="//head/meta"
nocontent="ignore" />
<!-- Hey look here! Nice new css selectors that everybody
can understand! -->
<replace css:theme="title"
css:content="title"
nocontent="ignore" />
<!-- For now, just copy the body text into a div we've got
in there for our blueprint css styling. -->
<copy css:theme="div.container"
css:content="body > *"
nocontent="ignore" />
</rules>
The theme hasn’t been fleshed out yet. For now I only apply the blueprint css stylesheets, basically:
<!DOCTYPE html>
<html>
<head>
<title>title</title>
<!-- Blueprint css framework. -->
<link rel="stylesheet"
href="/static/blueprint/screen.css"
type="text/css"
media="screen, projection" />
<link rel="stylesheet"
href="/static/blueprint/print.css"
type="text/css"
media="print" />
<!--[if IE]>
{% compress css %}
<link rel="stylesheet"
href="/static/blueprint/ie.css"
type="text/css"
media="screen, projection" />
{% endcompress %}
<![endif]-->
</head>
<body>
<div class="container">
<h1>Hoera</h1>
<p>Hurray! Sample content that will disappear!</p>
</div>
</body>
</html>
In the end, I’m pretty happy with the setup. I’ll probably port my two other projects over. And I’ll keep an eye open for more usecases for xdv!