Essays

2 years ago

Sunday, October 7, 2007

Woe Is iWeb

After our post about the inability to print pages created with iWeb, I decided to take a crack at the problem.

The first thing I did was to determine the exact cause of the problem. It turns out that the body_content <div> unnecessarily has the overflow property set to hidden. Since the <div> is relatively positioned it overflows the first page when printing, and therefore the overflow is hidden. By setting overflow: visible the problem would be fixed.

Unfortunately, iWeb writes this property as an inline style directly on the <div> itself, so there’s no way to override it. Even !important declarations with high selector specificity in external stylesheets don’t take precedence over inline styles. (This is unfortunate, in general.)

It was at this point we received a very friendly email from Mike Lee. He helpfully showed us that the printing problem doesn’t occur in Safari or when sending the page via Mail. This does make it clear that the iWeb developers were writing iWeb primarily for Safari. Not everyone is using Safari, though (we had been using Camino and Firefox). And while the Mail workaround let’s us print the page, it’s a big hack.

Mike’s suggestion was to write an XSLT stylesheet that would transform iWeb’s misbehaving inline CSS into something more palatable. And this is what I came up with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!– The identity template. –>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  <!– Add an ‘overflow: visible’ declaration to the body_content div. –>
  <xsl:template match="*[@id=’body_content’]/@style">
     <xsl:attribute name="style">
       <xsl:value-of select="concat(., ‘ overflow: visible;’)" />
     </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

This XSLT stylesheet uses an identity template to copy all attributes and nodes, changing only the ones overridden by other templates. Here, the only thing we want to override is the style attribute on the body_content <div>. In this case, we just concatenate the required declaration to the existing value of the attribute.

Unfortunately, when trying to run Mike’s page through this transform, it turns out the XHTML that iWeb generates is invalid. One of the (numerous) problems is that the <link> tags aren’t closed in the head. This makes the XSLT engine choke. Unlike the cause of the printing problem, though, this isn’t a simple browser incompatibility between how Safari and Camino interpret the overflow property. It’s just shoddy work on the part of the iWeb team.

Mike gave another suggestion: use Tidy to clean up iWeb’s mess. Since OS X 10.4 comes preinstalled with both the GNOME xsltproc utility and tidy, all that needs to be done is

tidy < input.html > fixed.html
xsltproc iweb_fix.xslt fixed.html > fixed.html

This little fix is something that maintainers of iWeb-generated pages will have to apply themselves before uploading their websites. Perhaps like so:

find /path/to/website/files -type f -iwholename ‘*.htm*’ -exec tidy -modify {} \; -exec –output {} xsltproc /path/to/iweb_fix.xslt {} \;
Trackback Comment

I suppose the thing to do would be to load the page using tidy into NSXML, then apply transformations or other DOM/XML magic before outputting the file into your intended format. I could probably whip you up a little application to do that if you tell me what format you want it in. Or, to put it another way, if you just want plain text, RTFD, or reformed HTML (with the hidden tag fixed) it would be pretty trivial to generate out of NSXML, and worse come to worst, we can use the power of application programming to fix any niggling annoyances that come along.

Ahh, tidy! Obviously! Thanks for the suggestion, Mike. I tried it and it cleans up iWeb’s markup beautifully. After that the XSLT stylesheet can properly drop in an overridden overflow: visible declaration to the style attribute on the offending <div>. I’ve updated the post to include that. Unfortunately, this looks like something that iWeb users will have to run their sites through before uploading them, for anybody to get any use out of this.

Hi,

I am using iWeb ‘09 and is encountering this exact problem. If I preview my pages or try to print it, it will only print the first page. I have tried your solution above, however it still don’t work.

Running the fix you suggested I received the following message:

find: -iwholename: unknown option
-bash: -exec: command not found

I then check the man page, and couldn’t find an entry for -iwholename, so I tried -iname, but then I received the following message:

find: -exec: no terminating “;” or “+”
-bash: -exec: command not found

I’m a total newbie in this, and I’m now stumped. Would you have a suggestion?

Thanks lots in advance!

@Johansen: If you’re using an older version of find it won’t have the -iwholename option. If you’re using bash you might have to escape the statement terminator with a backslash. So, you want to do something like

-exec tidy -modify {} \; -exec –output {} xsltproc /path/to/iweb_fix.xslt {} \;
Thursday, March 11, 2010
11:00am