Diazo theme inheritance

by thijs

With old style theming in a package you could base your themes on Sunburst or classic. Creating themes based on frameworks got me to do the theming on the content side and then move the complete body over to the theme side. After several variations of one type of framework the constant duplication of resources, made me realize I needed some form of inheritance for this type of diazo theme. Check out diazotheme.frameworks and diazotheme.bootswatch for the result.

Why theme on the content side?

The Plone html structure has been set up with a sensible content order in mind. This is the same for most popular frameworks. They have also been created with reusable blocks of of tags and classes, like Plone. They have grid systems, typography and JavaScript based on those reusable code blocks. And though the execution between different frameworks and Plone differs, the overall idea is the same.

Diazo is a great tool when you want to change similar html structures across a lot of templates. With only a few lines of code in the rules file you can change al the submit inputs into buttons. If you would want to do that in an oldstyle theme you would have to change dozens of templates. There was a question on the Plone UI Team mailing list about making it easier to plug Plone into some popular frameworks. This made me think that diazo would be the tool to do it. You don’t want to redo a complete template set in order for the html to fit with another framework. By switching out Plone’s reusable structures with the framework ones on the content side, you keep the templates intact but turn the html into what Plone would look like in another framework.

Queue Bootstrap

I figured I’d try and start with the most popular kid on the block and theme me some Bootstrap. Not looking around whether or not anyone had done it already. Starting off I was just moving Plone content into the example templates they have in their documentation. But then I got to the grid system. Since Bootstrap already has div.row and only uses a different syntax for the columns within, the best way was to swap out the div.cell with the Bootstap divs.

One thing led to another and I was starting to see swappable structures all over the place. Several iterations and themes later (I was also working on some easy starter themes, which of course also had to have a Bootstrap one, not having seen the example theme…), I was duplicating the same framework files all over the place. Not only that, but also huge chunks of rule file. Being human, in all that copying some sloppiness will occur and I noticed that there is no problem using resources from other themes. I also ran into diazotheme.bootstrap (which was also the name I was working under) which uses XIncludes to move some recurring rules to a separate file. These two “discoveries” are the basis for diazo theme inheritance or using a parent themes resources and rules.

The premise for framework themes

I ran into Bootswatch, which gives you a load of new stylesheets that work with Bootstrap, different themes if you will. Every Bootswatch theme needs 80% of the Bootstrap theme’s resources and 99% of its rules. What did I want from a framework theme:

  • No adaptation of the framework files itself, so you can copy over a new version whenever one is available.
  • Reuse the resources of the framework theme for other themes based on that framework.
  • Reuse the template of the framework theme for other themes based on that framework.
  • Reuse the rules that mold the content.
  • Edit the rules files only in one place
  • A childtheme should only need it’s unique resources and the files to define the theme (manifest.cfg, preview.png, rules.xml)

The setup

Parent theme

Create a package (I tend to use paster create -t Plone diazotheme.*) and copy in the framework files. Some frameworks come with an html example, for others you need to find it online, also copy that in and then do not touch them anymore. I tend to want to change directory names and structures to my preference, I DO NOT DO THIS FOR FRAMEWORK FILES. If you feel you need other resources outside of the framework resources, keep them separate from the framework resources and out of the framework directories. Do think twice before adding any extra resources, wouldn’t they fit better in a child theme?

Then setup the diazo theme, by adding rules.xml, preview.png and manifest.cfg. Do the theming until you think the rules are done. Chop the rules up into sensible blocks with XIncludes and move them into separate files. Think of likely candidates for being done differently in a child theme while keeping the rest of the rules intact. One block you will at least want is the framework stylesheets, because most likely a theme will override them. The easiest is to have your rules file only have rules you are certain will never be needed in a child theme. And even then have as little rules in there as possible, the rest of the rules in XIncludes. I tend to copy the complete rules file into a child theme and then remove and change what I need. Removing XInclude one liners is easier then code blocks.

Child theme

Create a package (I tend to use paster create -t Plone diazotheme.*), add the unique resources (or start creating them later on) and setup the diazo theme. Add a preview.png and manifest.cfg. Copy over the rules.xml and start tweaking them.

Remember to add the framework theme as a dependency to the child theme.

You can see a working implementation in the diazotheme.frameworks (parent) and diazotheme.bootswatch (child).

Pros & Cons

Pros

  • Works surprisingly well in putting Plone on other frameworks
  • Dry and clean solution
  • Easy for child themes if you don’t need to change much

Cons

  • Definitely in the Advanced theming department for the parent theme
  • Will probably not work too well with through the web editing

Plone

Diazo, HTML5 and XSL fun

by thijs

So everything you needed to do for xdv to get it to go HTML5 is now no longer necessary. I thought I’d have to use a registry.xml to be able to have a HTML5 doctype, which wouldn’t help much with the zip deployment of themes. But yesterday I saw it set in a manifest.cfg on the ploneconf (2011).

An example HTML5 manifest.cfg file:

[theme]
title = My Theme
description = Description of your theme
rules = /++theme++my.theme/directory/rules.xml
prefix = /++theme++my.theme/directory
doctype = <!DOCTYPE html>

Another nifty little trick I’ve seen yesterday was the use of xsl:apply-templates and css:select. For instance if you want to do something silly with your breadcrumb.

<xsl:if css:test="#breadcrumb-1">
  <append css:theme="#breadcrumb">
    <xsl:for-each css:select="#portal-breadcrumbs > span:not(#breadcrumbs-you-are-here) > *" method="raw">
      <xsl:choose>
        <xsl:when css:test=".breadcrumbSeparator">
          <span class="separator"> > </span>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates css:select="a, span"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </append>
</xsl:if>

The above example basicly does this:

  1. xsl:if
    This tests if the “breadcrumb-1″ id is available (when you have more than just home)
  2. append
    Select the div with the breadcrumb id
  3. xsl:for-each
    Loops through all the children of spans,  directly under portal-breadcrumbs, that do not have the “breadcrumbs-you-are-here” id.
  4. xsl:choose
    For when you have multiple scenarios. In this case sort of if else, but you could have lots of different cases.
  5. xsl:when
    First scenario, in this case selecting the breadcrumb separator and changing it.
  6. span
    Yes, you can add html structure like this.
  7. xsl:otherwise
    If none of the above scenario’s match, then do this.
  8. xsl:apply-templates
    Put the content you select into the theme side. In case of a for-each the selection is relative to the for each select.

The xsl:apply-templates bit I used to do by useing xsl:copy-of, which put the content there, but takes it out of the xdv loop. The xsl:apply-templates way leaves it in.

Other fun tricks

You can use an href to draw in content from outside of the content page. In plone you can use it for browser view for instance. The following example gets in the html in the @@login-form browser view:
<append css:theme=”” css:content=”form” href=”@@login_form” />

To select comments, for instance one that has the word ‘base’ somewhere in there use //comment()[contains(., 'base')]. The following example moves the base tag from the content to the comments in the theme that contain the word base:
<replace theme=”//comment()[contains(., 'base')]” css:content=”base”/>

XDV and HTML5

by thijs

The greatest thing to me about XDV is that you can leave Plone as it is and alter nearly everything about it. Mostly xdv will suffice, but when necessary you can even grab for xsl. You’re not even doctype bound. I’ve been working on an XDV theme based on HTML5 boilerplate.

Compared to my previous post on moving from xhtml 1.0 transitional to strict, this was a bit less of a picknick. More like a night in the wild having to catch and collect your own food. I ran into some major hurdles. Here is how I crossed them.

First off, get HTML5 Boilerplate and create a basic theme. Then start with the rules file,  starting off with changing the doctype according to Denys his method.

<?xml version="1.0" encoding="UTF-8"?>
<xdv:rules xmlns:xhtml="http://www.w3.org/1999/xhtml"
 xmlns:xdv="http://namespaces.plone.org/xdv"
 xmlns:css="http://namespaces.plone.org/xdv+css"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Set output to HTML5 -->
<xsl:output doctype-public="html" doctype-system="" />

Mostly I start with filling the head, working my way down through the HTML. Now after the doctype is where the trouble started. Wanting to use most of the plone metatags, but have the html5 charset and the boilerplate IE edge statement proved more of a problem than I anticipated. Though mostly because I needed to refresh my xpath expressions. I went through a few XSL attempts after realizing i could just do it with regular XDV.

<!-- Pull in Plone Meta -->
<!-- Exclude HTML5 specific meta defined in Boilerplate -->
<xdv:after
     theme="/html/head/meta[last()]"
     content="/html/head/meta[
         not(@content='IE=edge' or
             @content='text/html; charset=utf-8')]" />

Next up, were the script tags. The XSL transform caused them to self close, rendering them invalid (Gotta love that validator). They always need a closing tag. I did not fill any scripts, because I wanted them all to be static resources. This was not a problem when turning xhtml to strict so I was a bit baffled. Turns out that XSLT works different when you have an xhtml doctype. It turns out all empty tags were automatically self closed. The solution for this was adding comments to all the non void tags (tags that are not allowed to self close) or part of the solution at least. This issue had a tail. Beware that script tags need javascript comments instead of regular html ones to be valid.

All the issues seemed to be solved, so I started filling content until I was ready to run it through a validator again. Once again I ran into self closed tags that were not allowed to be closed. This time it was span’s and div’s from the content side. Looking through posts and forums I ran into the problem, but not really a feasible solution. After a lot of part solutions and even a post from Laurence Row, I ended up with the following XSL. It seems to work, but it has not been greatly tested yet.

<!-- Get empty elements -->
<xsl:template match="*[not(node())]">
 <xsl:copy>
 <xsl:for-each select="@*">
 <xsl:variable name="LocalName" select="local-name()"/>
 <xsl:attribute name="{$LocalName}">
 <xsl:value-of select="."/>
 </xsl:attribute>
 </xsl:for-each>
 <xsl:comment/>
 </xsl:copy>
 </xsl:template>

<!-- Handle script tags with a valid comment of its own -->
<xsl:template match="script[not(node())]">
 <xsl:copy>
 <xsl:for-each select="@*">
 <xsl:variable name="LocalName" select="local-name()"/>
 <xsl:attribute name="{$LocalName}">
 <xsl:value-of select="."/>
 </xsl:attribute>
 </xsl:for-each>
 <xsl:text disable-output-escaping="yes">// Stop XDV from closing tag
 </xsl:text>
 </xsl:copy>
 </xsl:template>
 <xsl:template match="*[not(node())]">
 <xsl:copy>
 <xsl:copy-of select="@*"/>
 <xsl:comment/>
 </xsl:copy>
 </xsl:template>

<!-- Exclude void elements -->
<xsl:template match="
  @*|area[not(node())]|
  base[not(node())]|br[not(node())]|
  col[not(node())]|command[not(node())]|
  embed[not(node())]|hr[not(node())]|
  img[not(node())]|input[not(node())]|
  keygen[not(node())]|link[not(node())]|
  meta[not(node())]|param[not(node())]|
  source[not(node())]">
 <xsl:copy>
 <xsl:apply-templates select="@*|node()"/>
 </xsl:copy>
 </xsl:template>
<xsl:template match="area[not(node())]|base[not(node())]|br[not(node())]|
 col[not(node())]|command[not(node())]|embed[not(node())]|
 hr[not(node())]|img[not(node())]|input[not(node())]|
 keygen[not(node())]|link[not(node())]|meta[not(node())]|
 param[not(node())]|source[not(node())]">
 <xsl:copy-of select="."/>
 </xsl:template>

One more thing and then I close off. There’s an acronym in plone so, of course, you switch it for an abbr like so:

<!-- Flip acronym to abbr -->
<xsl:template match="acronym">
 <xsl:element name="abbr">
 <xsl:for-each select="@*">
 <xsl:variable name="LocalName" select="local-name()"/>
 <xsl:attribute name="{$LocalName}">
 <xsl:value-of select="."/>
 </xsl:attribute>
 </xsl:for-each>
 <xsl:value-of select="."/>
 </xsl:element >
 </xsl:template>
<xsl:template match="acronym">
 <xsl:element name="abbr">
 <xsl:copy-of select="@*"/>
 <xsl:value-of select="."/>
 </xsl:element>
 </xsl:template>

Update: Found a way to shorten the code. copy-of can strip the whole for-each blocks and the xsl:comment gets stripped, but leaves the closing tag in place. This removes the need for special casing the script element.

Let me know if you use it. Any changes I’ll post here.

Update 2: For Diazo all this is no longer necessary

Dutch Webguidelines and XDV trickery

by thijs

With Plone’s new theming mechanism it is a breeze to conform to a strict doctype necessary for the Dutch Web-guidelines (Webrichtlijnen Overheid). This post is actually long overdue since I’ve done this at least half a year ago, but still, better late then never.

I’ll start of giving the rules.xml used to do it and then I’ll explain the parts of it.

<?xml version="1.0" encoding="UTF-8"?>
<xdv:rules
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xdv="http://namespaces.plone.org/xdv"
xmlns:css="http://namespaces.plone.org/xdv+css"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<!-- Strict will need rules to fix plone Transitional differences -->
<xsl:output
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
method="xhtml" />


<!-- Remove whitespace because of line ends breaking validation.
-->
<xsl:strip-space elements="ul ol dl" />


<!-- Remove name attribute from forms -->
<xdv:drop content="//form/attribute::name" />
</xdv:rules>

As you can see, I start of namespacing the different dialects in the rule file. A lot of the online tutorials don’t show it this way. They generally have the xdv namespace as the default. I started of like that but it caused validation errors because the default namespace got the namespace added to some of the tags. Namespacing everything explicitly solved this.

<xdv:rules
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xdv="http://namespaces.plone.org/xdv"
xmlns:css="http://namespaces.plone.org/xdv+css"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

The next step is to change the output doctype. I’ve focussed on getting the code to comply to xhtml 1.0 strict, but in theory it is also possible to turn it into html4.01 stict. For plone it’s easier to go for xhtml since it’ s already xhtml 1.0 transitional.

<xsl:output
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
method="xhtml" />


<!-- For html 4.01 you would use this code, the other rules on this page won't work to help validate that though, you'd have to find out for yourself what works. -->
<!--xsl:output
doctype-public="-//W3C//DTD HTML 4.01//EN"
doctype-system="http://www.w3.org/TR/html4/strict.dtd"/-->


Now our doctype for the XDV themed part of the site is shtml 1.0 strict. The content source is still transitional though. For the content to be valid we also need to make some changes to it. First off, the xsl transform caused whitespace characters to show up in places they were not allowed to show up. The issue was with character &13;.

I’ve solved this by selectively stripping whitespace. For now it is just stripped between list items. This is however a growing list. So far I haven’t run in to the problem anymore, but if I will I’ll update the items that need their whitespace stripped. Another option would be to strip all whitespace, but with this you would be risking stripping significant whitespace.

<!-- Remove whitespace because of line ends breaking validation.


This rule will only remove whitespace between li, dt and dd elements.
<xsl:strip-space elements="ul ol dl" />


The rules below will remove them all, which could cause trouble if
there is significant whitespace without text between two elements.
<xsl:strip-space elements="*" />
<xsl:preserve-space elements="pre" />
-->
<xsl:strip-space elements="ul ol dl" />

Another validation error was caused by the name attribute on forms. This was an easy strip. Most Plone forms already have an id. If you’re in a situation this is not the case you could decide, instead of dropping it, to set from name to id.

<!-- Remove name attribute from forms -->

<xdv:drop content="//form/attribute::name" /></xdv:rules>

Python 2.4 on Ubuntu 10.04

by thijs

The installation of python2.4 on Ubuntu 10.04 had me pulling the hair from my head. I needed to deploy a Plone project using Fabric and buildout-source-release and python2.4, but the latter has been dropped for Ubuntu 10.04. Through dirty hacks it was possible to release, but now I’ve got the propper solution.

Using: http://plone.org/documentation/kb/installing-a-plone-buildout-on-ubuntu and http://davidjb.com/blog/2010/05/installing-python-2-4-on-ubuntu-10-04-lucid-lynx
I finally ended up with:

# Jaunty 2.4 packages
wget http://mirror.aarnet.edu.au/pub/ubuntu/archive/pool/main/p/python2.4/python2.4-minimal_2.4.6-1ubuntu3.2.9.10.1_i386.deb -O python2.4-minimal.deb
wget http://mirror.aarnet.edu.au/pub/ubuntu/archive/pool/main/p/python2.4/python2.4_2.4.6-1ubuntu3.2.9.10.1_i386.deb -O python2.4.deb
wget http://mirror.aarnet.edu.au/pub/ubuntu/archive/pool/main/p/python2.4/python2.4-dev_2.4.6-1ubuntu3.2.9.10.1_i386.deb -O python2.4-dev.deb
sudo dpkg -i python2.4-minimal.deb python2.4.deb python2.4-dev.deb

# Setup tools
wget http://peak.telecommunity.com/dist/ez_setup.py sudo python2.4 ez_setup.py -U setuptools

# Clean up
rm python2.4-minimal.deb python2.4.deb python2.4-dev.deb ez_setup.py

Update: After upgrading to Ubuntu 10.10 the instructions still seem to work.

Not caching certain plone templates in Varnish

by thijs

For a customer I needed to have an old school custom Plone template not to be cashed. The site was put behind varnish and just adding “no-cache” headers did not work.

The solution was creating an extra rule in the “Cache Configuration Tool” (http://yourplonecms.com/portal_cache_settings/with-caching-proxy/rules), which allows for quite a lot of customization.

To the top of the existing rule set, add a copy of the plone-templates. In the rule under “Templates” add your template id and for the “Header Set for …” set both dropdowns to “Do not cache”. This should do the trick, at least it did for me.

DOM Scripting; the book by Jeremy Keith

by thijs

This book has proven to be a great read. It is: easily written, focussed on web designers, has great regard for web standard and builds up nicely by showing all the steps and then sticking them together in a fictional case.

Based on semantic HTML and CSS the book shows you how to enhance the user experience with JavaScript without adding relevant content. As a web developer with python experiance but less knowledge of JavaScript this book quickly clarifies how to do things the right way.

Starting of with a brief history of JavaScript, followed by basic syntax explanation. It then gives an explanation of the DOM. Through a set of carefully explained examples of javaScript enhancements, like for example: an image gallery and folding of content based on a subnavigation, the book leads to putting it all together in a final example case.

After reading the book it will be easier to recognise the good JavaScript from the bad. The frequently used “copy/paste” code, becomes higher quality (if you take the trouble to read the code before “copy/pasting”). You also want to start writing scripts yourself because after the book JavaScript looks easy and fun.

Plone 3.2.1 ImportError

by thijs

While updating a plone 3.1.7 instance to 3.2.1 I all of the sudden had the following import error:

    ImportError: No module named ImplPython

Searching the net I only found irrelevant solutions to my situation. I had an other plone 3.2.1 instance that used to work, so I checked if it would still run and it did. Creating a test instance of that buildout, once again didn’t work. Running a div between the two instance files showed 3 differences.

zope.component-3.5.1 was now zope.component-3.6.0

and two missing packages

zope.deferredimport
zope.deprecation

(both dependencies of zope.component-3.5.1)

Version pinning zope.component-3.5.1 in the buildout solved the import error.

[buildout]
versions = versions
[versions]
zope.component=3.5.1

Rsync

by thijs

Our office network has horrible download speeds, it is more efficient to zip a file before copying it. (No longer slow but still nice to not forget this)

rsync -avz --progress server:source target

Override portlets or Subclassing

by thijs

On http://transcyberia.info/archives/39-customizing-navigation-in-Plone3.html I found a great article on how to subclass the navigation portlet. Explanations and all. This entry is based on that article but doesn’t have all the nice explanations.

For a generic plone 3 portlet with a template portlet.pt and a module named portlet.py, this is what you need to do to subclass it. I tend to create a portlets folder in my porducts, which you have to register in the same way as the browser folder from your theme is registered. Don’t forget the __init__.py and a configure.zcml!

Copy portlet.pt template from the source egg into your theme’s portlets/ directory. Don’t copy portlet.py, but instead create your own portlet.py. It needs only the following measly five lines of code:

from source.egg.portlet import Renderer
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

class MyPortletRenderer(Renderer):
     render = ViewPageTemplateFile('portlet.pt')

In portlets/configure.zcml put the following lines:

      <plone:portletRenderer
       portlet="source.egg.portlet.IPortletInterface"
       layer=".interfaces.IThemeSpecific"

       />

If, like in this example, the template in the renderer is called render (so render = ViewPageTemplateFile(‘portlet.pt’)) and not index or _template or something the like, you just use the template instead of creating a class for it in a special portlet.py. The subclassing also works with multiple templates or differently named ones.

<plone:portletRenderer
   portlet="source.egg.portlet.IPortletInterface"
   template="portlet.pt"
   layer=".interfaces.IThemeSpecific"
   />
Posted in Plone | Comments Off