“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:
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
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. 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:
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.
Googling and reading my way through various websites, I settled for the following setup.
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!
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):