This is the second post in a short series about the ideas, trials and tribulations of my first theme product. I’ll be posting the whole story in one place when the series is complete.
The Theme Product
I’ve done a lot of Plone development over the past couple of years, but I’ve never done anything with theming. This is my first attempt at theming Plone. From what I’ve seen, it’s probably good that I’ve waited. :) The way themes are handled in Plone has changed a lot over the past couple of years, and I get the feeling that if I had become a theming pro when I first started with Plone, this could prove an even greater challenge.
Another good reason that I’ve waited, whichb contributes in the hair-pulling-reduction-department: there’s a plone3_theme template in the ZopeSkel suite. Score!
I first saw the template in action at the Plone conference in DC last year, during Rob Porter’s “Theming a Plone 3.1 site from start to finish” presentation. It seemed like a real blessing to theme developers: it’s got the wiring necessary to build an old-school “skins layer” theme, and also add in viewlets and other zope3 tech that is available to us in modern times. It’s a bit complicated at first glance, but once you get your bearings and start customizing things, you realize it’s quite a useful tool.
If you’ve never messed with ZopeSkel before, be sure to check out the PyPI page and My quickstart guide to get up and running.
First, as I often do when starting a new Plone project, I start with a plone 3 buildout skeleton (I like to name my buildout after the egg that’s being developed):
$ cd ~ $ paster create -t plone3_buildout my.theme Selected and implied templates: ZopeSkel#plone3_buildout A buildout for Plone 3 projects Variables: egg: my.theme package: mytheme project: my.theme Enter zope2_install (Path to Zope 2 installation; leave blank to fetch one) ['']: Enter plone_products_install (Path to directory containing Plone products; leave blank to fetch one) ['']: Enter zope_user (Zope root admin user) ['admin']: Enter zope_password (Zope root admin password) ['']: admin Enter http_port (HTTP port) [8080]: Enter debug_mode (Should debug mode be "on" or "off"?) ['off']: on Enter verbose_security (Should verbose security be "on" or "off"?) ['off']: on ... ----------------------------------------------------------- Generation finished You probably want to run python bootstrap.py and then edit buildout.cfg before running bin/buildout -v See README.txt for details -----------------------------------------------------------
The answers to the questions are pretty straightforward; my usual modus operandi when creating a new development buildout.
So now that I’ve got my buildout, I need to create a skeleton for the theme, and then wire it all up in my buildout.cfg.
$ cd my.theme/src $ paster create -t plone3_theme my.theme Selected and implied templates: ZopeSkel#basic_namespace A project with a namespace package ZopeSkel#plone A Plone project ZopeSkel#plone3_theme A Theme for Plone 3.0 Variables: egg: my.theme package: mytheme project: my.theme Enter namespace_package (Namespace package (like plonetheme)) ['plonetheme']: my Enter package (The package contained namespace package (like example)) ['example']: theme Enter skinname (The skin selection to be added to 'portal_skins' (like 'My Theme')) ['']: MY Theme Enter skinbase (Name of the skin selection from which the new one will be copied) ['Plone Default']: Enter empty_styles (Override default public stylesheets with empty ones?) [True]: False Enter include_doc (Include in-line documentation in generated code?) [False]: Enter zope2product (Are you creating a Zope 2 Product?) [True]: Enter version (Version) ['1.0']: 0.1 Enter description (One-line description of the package) ['An installable theme for Plone 3.0']: MY base theme that other specific themes are based on Enter long_description (Multi-line description (in reST)) ['']: Enter author (Author name) ['Plone Collective']: Josh Johnson Enter author_email (Author email) ['product-developers@lists.plone.org']: lionface.lemonface at gmail dot com Enter keywords (Space-separated keywords/tags) ['web zope plone theme']: my base jjmojojjmojo Enter url (URL of homepage) ['http://svn.plone.org/svn/collective/']: http://lionfacelemonface.wordpress.com/2009/01/12/adventures-in-theming Enter license_name (License name) ['GPL']: Enter zip_safe (True/False: if the package can be distributed as a .zip file) [False]: ... ------------------------------------------------------------------------------ The project you just created has local commands. These can be used from within the product. usage: paster COMMAND Commands: addcontent Adds plone content types to your project For more information: paster help COMMAND ------------------------------------------------------------------------------ Running /home/jj/zopeskel/bin/python setup.py egg_info
Most of the questions are old news if you’ve done ZopeSkel-based products before, but there are a few questions that are little more confusing than the usual plone product questions.
-
Enter skinname (The skin selection to be added to ‘portal_skins’ (like ‘My Theme’)) This question relates to giving your theme a skin name. This helps isolate your changes so that the end user can switch themes later.
-
Enter empty_styles (Override default public stylesheets with empty ones?) This question is asking you if you’d like all of the default plone stylesheets replaced with empty shells. Answering ‘True’ to this question will essentially remove all of Plone’s default styling. This is good if you’d like to start completely from scratch, but in my case, I want to leave a large amount of the default plone styling intact, so I specified ‘False’.
-
Enter skinbase (Name of the skin selection from which the new one will be copied) I’m not a hundred percent sure what this is. I believe it has to do with GenericSetup and how the skin is initialized, but I haven’t tried anything but the default so far.
-
Enter include_doc (Include in-line documentation in generated code?)
This is a switch that turns on or off a whole bunch of inline documentation. The first time you create a theme product, it can be very very helpful, but is just a lot of extra bytes in your code otherwise. I’ve opted to turn it off here. It can also be useful to create an additional theme product with the inline docs turned on so you can refer to them as you develop your target theme.
Now that I’ve got a plone theme, it just needs to be wired up into plone via buildout.cfg, settting up my.theme as a “development egg”. This is accomplished using the ‘develop’ configuration directive under the [buildout] section, and the ‘zcml’ and ‘eggs’ directives under the [instance] section.
[buildout]
...
develop =
src/my.theme
...
[instance]
eggs =
${buildout:eggs}
${plone:eggs}
my.theme
...
zcml =
my.theme
What’s Next
At this point I’ve got a working plone theme that’s ready to be customized. My first step in that direction will be to create my own custom viewlet manager.