[z3-checkins] r30757 - in z3/deliverance/branches: mphandler noappmap noappmap/content noappmap/doc noappmap/etc noappmap/themes noappmap/themes/simple noappmap/themes/spiral noappmap/themes/spiral/IE7 noappmap/themes/spiral/fwfiles
paul at codespeak.net
paul at codespeak.net
Mon Jul 31 10:34:40 CEST 2006
Author: paul
Date: Mon Jul 31 10:34:19 2006
New Revision: 30757
Added:
z3/deliverance/branches/mphandler/
z3/deliverance/branches/mphandler/contentmap.py
z3/deliverance/branches/mphandler/contentrenderer.xsl
z3/deliverance/branches/mphandler/mphandler.conf
z3/deliverance/branches/mphandler/mphandler.py
z3/deliverance/branches/mphandler/samplemap.xml
z3/deliverance/branches/noappmap/
z3/deliverance/branches/noappmap/README.txt
z3/deliverance/branches/noappmap/content/
z3/deliverance/branches/noappmap/content/index.html
z3/deliverance/branches/noappmap/content/intro.html
z3/deliverance/branches/noappmap/doc/
z3/deliverance/branches/noappmap/doc/CHANGES.rst
z3/deliverance/branches/noappmap/doc/DEBUGGING.rst
z3/deliverance/branches/noappmap/doc/INSTALL.rst
z3/deliverance/branches/noappmap/doc/INTRO.rst
z3/deliverance/branches/noappmap/doc/NOTES.rst
z3/deliverance/branches/noappmap/doc/NewWorld.rst
z3/deliverance/branches/noappmap/etc/
z3/deliverance/branches/noappmap/etc/thememap.xml
z3/deliverance/branches/noappmap/mpfilter.conf
z3/deliverance/branches/noappmap/mpfilter.py
z3/deliverance/branches/noappmap/themecompiler.xsl
z3/deliverance/branches/noappmap/thememap.py
z3/deliverance/branches/noappmap/themes/
z3/deliverance/branches/noappmap/themes/simple/
z3/deliverance/branches/noappmap/themes/simple/sampletheme.xml
z3/deliverance/branches/noappmap/themes/simple/simpletheme.css
z3/deliverance/branches/noappmap/themes/spiral/
z3/deliverance/branches/noappmap/themes/spiral/IE7/
z3/deliverance/branches/noappmap/themes/spiral/IE7/filesused.txt
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-content.htc (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-core.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-css-strict.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-css2-selectors.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-css3-selectors.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-dhtml.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-dynamic-attributes.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-fixed.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-graphics.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-html4.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-ie5.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-layout.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-load.htc (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-object.htc (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-overflow.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-quirks.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-recalc.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-server.css (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-squish.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-standard-p.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-xml-extras.js (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/bigben-bg.css
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/flower-bg.css
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/folkswagon.js
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/lightning-bg.css
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/shell-bg.css
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/shell-bg.jpg (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/shell-blue.jpg (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/shell-fade.jpg (contents, props changed)
z3/deliverance/branches/noappmap/themes/spiral/fwfiles/shuttle-bg.css
z3/deliverance/branches/noappmap/themes/spiral/sarissa.js
z3/deliverance/branches/noappmap/themes/spiral/spiral.css
z3/deliverance/branches/noappmap/themes/spiral/spiral.js
z3/deliverance/branches/noappmap/themes/spiral/spiraltheme.html
Log:
New branches for theme refactor and restart of content map
Added: z3/deliverance/branches/mphandler/contentmap.py
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/mphandler/contentmap.py Mon Jul 31 10:34:19 2006
@@ -0,0 +1,52 @@
+"""
+contentmap - Manage an in-memory map of content and renderers.
+
+This module reads a map of resources in an XML file and provides
+several services:
+
+ o Pre-calculate certain statistics
+
+ o Retrieve a resource that is published online
+
+ o Render that resource to XHTML
+"""
+
+import os
+from lxml import etree
+
+class ContentMap:
+
+ def __init__(self, contentmapfn=None):
+
+ # Open the content file, make a tree, and process XIncludes
+ module_dir = os.path.dirname(os.path.abspath(__file__))
+ if not contentmapfn:
+ layoutsfn = os.path.join(module_dir, "samplemap.xml")
+ self.tree = etree.ElementTree(file=layoutsfn)
+ self.tree.xinclude()
+
+ # Published resources that come from the appmap content (vs. an
+ # html file on disk) need to get rendered to XHTML first. The
+ # rendererprocessor XSLT does this.
+ rendererfn = os.path.join(module_dir, "contentrenderer.xsl")
+ rendererdoc = etree.ElementTree(file=rendererfn)
+ self.rendererprocessor = etree.XSLT(rendererdoc)
+
+
+ def publish(self, path_info):
+ """Find a resource, generate markup, and apply theme"""
+
+ # Pass path_info in as xslt parameter to XSLT that renders nodes
+ # in the appmap
+ response = self.rendererprocessor(self.tree,
+ pathinfo="'%s'" % path_info)
+
+ return str(response)
+
+def main():
+ contentmap = ContentMap()
+ response = contentmap.publish("providers.joelburton")
+ print response
+
+if __name__ == "__main__":
+ main()
Added: z3/deliverance/branches/mphandler/contentrenderer.xsl
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/mphandler/contentrenderer.xsl Mon Jul 31 10:34:19 2006
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:at="http://www.plone.org/archetypes" exclude-result-prefixes="at html" version="1.0">
+ <xsl:output indent="yes"/>
+ <xsl:param name="siteurl">/sandboxes/z3/deliverance/branches/mphandler/content</xsl:param>
+ <xsl:param name="pathinfo">providers.zea</xsl:param>
+ <xsl:variable name="contentnode" select="id($pathinfo)"/>
+ <xsl:template match="/">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ <xsl:value-of select="$contentnode/@title"/>
+ </title>
+ </head>
+ <body>
+ <div id="navtree">
+ <xsl:apply-templates select="id('root')" mode="navtree"/>
+ </div>
+ <div id="pagecontent">
+ <xsl:apply-templates select="$contentnode"/>
+ </div>
+
+ </body>
+ </html>
+ </xsl:template>
+ <xsl:template match="at:collection" mode="navtree">
+ <div>
+ <h2>sitenav</h2>
+ <ul>
+ <xsl:for-each select=".//*[@name]">
+ <li>
+ <a href="{$siteurl}/{@name}">
+ <xsl:value-of select="@title"/>
+ </a>
+ </li>
+ </xsl:for-each>
+ </ul>
+
+ </div>
+ </xsl:template>
+
+ <xsl:template match="at:providers">
+ <ul>
+ <li>Item one</li>
+ <xsl:for-each select="at:provider">
+ <li>
+ <xsl:value-of select="@title"/>
+ </li>
+ </xsl:for-each>
+ </ul>
+ </xsl:template>
+
+ <xsl:template match="at:provider">
+ <p>Title:
+ <xsl:value-of select="@title"/>
+ </p>
+ </xsl:template>
+
+ <xsl:template match="at:localfile">
+ <xsl:copy-of select="html:html/html:body/*"/>
+ </xsl:template>
+
+</xsl:stylesheet>
Added: z3/deliverance/branches/mphandler/mphandler.conf
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/mphandler/mphandler.conf Mon Jul 31 10:34:19 2006
@@ -0,0 +1,10 @@
+# Use an Include directive in your main Apache conf file to
+# add these configuration instructions to your Apache.
+
+LoadModule python_module modules/mod_python.so
+
+<Directory /Users/paul/sandboxes/z3/deliverance/branches/mphandler>
+ SetHandler mod_python
+ PythonHandler mphandler
+ PythonDebug On
+</Directory>
Added: z3/deliverance/branches/mphandler/mphandler.py
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/mphandler/mphandler.py Mon Jul 31 10:34:19 2006
@@ -0,0 +1,29 @@
+"""
+mphandler - mod_python content handler for Deliverance
+
+This module bridges an Apache content handler, implemented in
+mod_python, to a Deliverance 'content map'. The content map is
+an in-memory tree of resources, as XML, that can be rendered
+into XHTML.
+
+In most cases, the output of this handler is then the input to
+a Deliverance theme.
+"""
+
+from mod_python import apache
+from contentmap import ContentMap
+contentmap = ContentMap() # Called once at module import time
+
+def handler(req):
+ """Basic filter applying to all mime types it is registered for"""
+
+ # Get the path, strip off leading slash, and convert to a
+ # dotted notation for xml:id compatibility
+ path_info = req.path_info[1:]
+ dotted_path = path_info.replace("/", ".")
+
+ response = contentmap.publish(dotted_path)
+ req.content_type = "text/html"
+ req.write(response)
+
+ return apache.OK
Added: z3/deliverance/branches/mphandler/samplemap.xml
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/mphandler/samplemap.xml Mon Jul 31 10:34:19 2006
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="contentrenderer.xsl"?>
+<contentmap xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:at="http://www.plone.org/archetypes"
+ xmlns="http://www.plone.org/deliverance">
+ <content>
+ <at:collection xml:id="root" xmlns="http://www.plone.org/archetypes" title="Home">
+ <providers name="providers" xml:id="providers" title="Providers">
+ <provider name="providers/enfold" xml:id="providers.enfold" title="Enfold"/>
+ <provider name="providers/zea" xml:id="providers.zea" title="Zea Partners"/>
+ <provider name="providers/joelburton" xml:id="providers.joelburton"
+ title="Joel Burton"/>
+ </providers>
+ <!--
+ <localfile name="localhello" xml:id="localhello" title="Local Hello File">
+ <xi:include href="localhello.html"/>
+ </localfile>
+ -->
+ </at:collection>
+ </content>
+</contentmap>
Added: z3/deliverance/branches/noappmap/README.txt
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/README.txt Mon Jul 31 10:34:19 2006
@@ -0,0 +1,76 @@
+=======================================
+Deliverance, high-speed themes for Zope
+=======================================
+
+Quick Start
+-----------
+
+1) Install lxml.
+
+2) cd to the directory containing this README.
+
+3) python ./thememap.py
+
+This runs the timeit function, showing average time to apply a simple theme.
+
+
+Quick mod_python Start
+----------------------
+
+1) Edit mpfilter.conf and point it to where you put the SVN checkout.
+
+2) In your Apache httpd.conf file, add a line like this::
+
+ Include /Users/me/sandboxes/deliverance/trunk/mpfilter.conf
+ (or wherever is the location of the checkout)
+
+3) Shut Apache down and restart.
+
+4) Keep an eye on the Apache error log::
+
+ tail -f logs/error_log
+
+5) Open a URL like this (or however you have your HTML files pointed to on
+whichever port)::
+
+ http://localhost:9000/sandboxes/deliverance/trunk/
+
+6) If that works, click on the on the "content" directory or go to this URL::
+
+ http://localhost:9000/sandboxes/deliverance/trunk/content/intro.html
+
+
+Customization Quick Start
+-------------------------
+
+1) Edit ``themes/simple/sampletheme.xml`` and add the following snippet
+**inside** the ``<div id="pageframe">``::
+
+ <div id="pageauthor">Theme section for author</div>
+
+2) Edit ``content/index.html`` and add the following in the ``<head>``:
+
+ <meta name="dc.creator" content="Your Name"/>
+
+3) Edit ``etc/thememap.xml`` and add a rule like the following::
+
+ <replace theme="//html:div[@id='pageauthor']"
+ content="/html:html/html:head/html:meta[@name='dc.creator']/@content"/>
+
+4) Restart Apache and reload the page.
+
+
+How Does This Work?
+-------------------
+
+The doc directory contains more information on the why and what for Deliverance.
+Here's the short version:
+
+1) A configuration "map" points at a pile of HTML artifacts that look the
+way you'd like your site to look. Let's call this look-and-feel the "theme".
+
+2) A rule file defines boxes in that theme that should get filled by boxes
+coming from the dynamic side.
+
+3) At startup, a one-time compilation processes turns the theme into a
+high-speed XSLT processor. You don't need to learn XSLT to use Deliverance!
Added: z3/deliverance/branches/noappmap/content/index.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/content/index.html Mon Jul 31 10:34:19 2006
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Hello World Content Page</title>
+ </head>
+ <body>
+ <p>Hello world, banjos everywhere.</p>
+ </body>
+</html>
\ No newline at end of file
Added: z3/deliverance/branches/noappmap/content/intro.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/content/intro.html Mon Jul 31 10:34:19 2006
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Deliverance</title>
+ </head>
+ <body>
+ <div class="document" id="deliverance">
+ <div class="section" id="content-deliver-for-cms-systems">
+ <h1>
+ <a name="content-deliver-for-cms-systems">Content delivery for CMS systems</a>
+ </h1>
+ <p>CMS systems, particularly in Zope, excel at the structured environment of content
+ <em>production</em>. This area places a strong emphasis on security,
+ workflow, metadata, and other content services.</p>
+ <p>For content <em>delivery</em> on public sites, though, some of this machinery is
+ overkill. The framework for content production has a nasty side effect of
+ killing performance for content delivery, making reliability and debugging a
+ challenge, and forcing other audiences (like web designers in charge of
+ look-and-feel) to learn another way to do things.</p>
+ <p>For this reason, many ECM packages make a formal distinction between content
+ production and content delivery.</p>
+ <p>Deliverance is a lightweight, semi-static system for content delivery of CMS
+ resources. It runs in mod_python, generating branded pages and navigation
+ elements, giving high-performance throughput to anonymous visitors. Its primary
+ benefits:</p>
+ <ul>
+ <li>High performance</li>
+ <li>Simple re-branding</li>
+ <li>Trusted stack</li>
+ <li>Extreme productivity</li>
+ </ul>
+ <p>It is focused on audiencces that want:</p>
+ <ul>
+ <li>Predictable delivery to anonymous visitors</li>
+ <li>Some portion of an airgap (logical/physical) between the CMS and the live
+ site</li>
+ <li>Integration with mainstream systems and technologies</li>
+ </ul>
+ <p>This document discusses how the system works, then revisits the benefits in
+ detail.</p>
+ </div>
+ <div class="section" id="overview">
+ <h1>
+ <a name="overview">Overview</a>
+ </h1>
+ <p>Deliverance has two major parts:</p>
+ <blockquote>
+ <p>o <em>Themes</em>. These apply a consistent look-and-feel to content that
+ streams through Apache. This content can be on the filesystem, in Zope with
+ mod_proxy, or using the other part of Deliverance. In a nutshell, a theme is
+ an HTML file (plus the CSS, images, etc.) containing boxes that get filled
+ by content.</p>
+ <p>o <em>Content maps</em>. A description of the content on a site, including
+ metadata and different organization schemes. The content map also has views
+ that, inside Deliverance, can generate HTML for navigation and other
+ purposes.</p>
+ </blockquote>
+ <p>Each of these can be used without the other.</p>
+ </div>
+ <div class="section" id="how-it-works">
+ <h1>
+ <a name="how-it-works">How It Works</a>
+ </h1>
+ <p>In a nutshell, Deliverance gets an XML map describing all the published content
+ at a point in time. It uses this map to draw navigation elements and issue HTTP
+ requests for content of single resources. Finally, a "theme"
+ provides the HTML to return with named boxes to be filled by rules.</p>
+ <p>Let's first introduce some major concepts, then walk a request through from start
+ to finish, using these concepts.</p>
+ <p>1) <em>Theme</em>. Web designers don't want to learn anything new. ZPT tried to
+ embrace this, but by the time the ZPT developer has injected all the tal and
+ refactored everything into macros, the web designer can't possible continue.</p>
+ <p>A theme is the corporate identity for a site. It is <em>not</em> a template, as
+ it has zero stuff in it beyond HTML.</p>
+ <p>A theme is created by saving the customer's home page and identifying the boxes
+ to be replaced. For example, <div id="sitemenu">
+ identifies a place where a generated menu should go. Web designers are familiar
+ with this, as CSS uses such selectors to apply style.</p>
+ <p>Deliverance has a ruleset that does the merge between the theme file and the
+ generated content. In essense, this rule file says: "Find 'site-menu'
+ in the theme and replace its children with the generated contents with an id of
+ 'generated-menu'."</p>
+ <p>The ruleset is under the control of the integrator, who bridges the gap between
+ what the CMS provides and what the UI designer makes available. This is done,
+ though, without touching anything on either side of the equation.</p>
+ <p>This allows the theme to be applied to all pages, without touching the pages. The
+ theme engine uses XSLT (via lxml) to perform the merge.</p>
+ <p>2) <em>Map</em>. By design, content delivery is separated from content
+ management. In fact, this separation acts as insulation. At various intervals,
+ the CMS makes an "edition" or a snapshot of its contents,
+ providing a map with metadata for all the contents that should be visible. (In
+ fact, the map could point at a certain <em>version</em> of a resource that
+ should be visible.)</p>
+ <p>This map is read by mod_python using lxml. It serves two functions:</p>
+ <p>a. <em>Navigation elements</em>. We can draw site menus and trees without
+ visiting the server. Since these can be done in XSLT, not only is the
+ performance very good, but we can draw many other kinds of pages. For example,
+ we can show all the contents modified in the last week, or all the contents in
+ France.</p>
+ <p>b. <em>Resource lookup</em>. The map controls how an incoming, virtual URL gets
+ mapped to a real resource. This means the URL space can be placeless. Content
+ can appear in multiple places. Equally, content from multiple CMSs, even
+ multiple remote hosts, can be integrated into the same map.</p>
+ <p>The identifier used for retrieving the content for the resource can be a normal
+ GET or a more complicated QUERY_STRING or even xml-rpc kind of lookup.</p>
+ <p>Note that the contents for many CMS resources are, in fact, very small amounts of
+ data. They could be cached inline in the content map and not looked up. For
+ frequent pages, this would provide a big win.</p>
+ <p>Finally, some resources in the map might be virtual, meaning the page can be
+ fully rendered in Deliverance. For example, a URL to show all the content with
+ the keyword of "CPS" can be serviced without a trip to the
+ server. All that is needed is an XSLT rule for generation. (Later, the XSLT
+ could be eliminated with a Python extension function in lxml.)</p>
+ <p>3) <em>Compilation</em>. The goal is high performance. There are certain aspects
+ that never change between requests:</p>
+ <ol class="loweralpha simple">
+ <li>The contents of the map.</li>
+ <li>The theme and the rule file for merging.</li>
+ <li>Site configuration, such as site menus.</li>
+ </ol>
+ <p>It makes no sense to re-parse DOMs and stylesheets on each request. Equally, it
+ makes no sense to have a multi-stage pipeline when several parts never change.</p>
+ <p>Deliverance gets a tremendous speedup by compiling the theme into a stylesheet.
+ It reads the XHTML file for the theme, identifies the nodes to be replaced, and
+ generates an XSTL with xsl:value-of and xsl:apply-template statements in the
+ right location. Compilation also inlines the map data into the XSLT so it
+ doesn't have to included later.</p>
+ <p>Compilation thus gives two benefits:</p>
+ <p>a. You can re-brand stuff without learning XSLT and without touching the HTML of
+ the theme file.</p>
+ <p>b. Most of the work needed for per-request transformations is done on startup.
+ Specifically, we avoid the 50ms hit that the "identity
+ transformation" pattern seemed to give.</p>
+ <p>4) <em>Retrieval</em>. mod_python has a Bobo-inspired publisher that walks the
+ URL, traversing Python objects using a set of rules.</p>
+ <p>Deliverance has a similar idea. The URL provides an identifier into the map file
+ to retrieve a map item. The map item then gives instructions on how to find the
+ content for the page and how to render it.</p>
+ <p>In most cases, some Python code will be issued to retrieve a page from the CMS.
+ For this, a very stripped-down skin will be used in the CMS, or perhaps no skin
+ at all. For example, the URL in the map file might request the DAV view of the
+ resource, thus giving just the data. For CMF-based systems, this is a 10x
+ speedup.</p>
+ <p>In other cases, the map might point to a virtual page, as discussed above.</p>
+ <p>The mapping provides some interesting possibilities for integration. First,
+ Deliverance could leverage Apache's infrastructure for retrieval and caching.
+ Second, libxml2 has several Python extension facilities (XPath functions, custom
+ resolvers) that allow the map to act as an integration facility. Simply put some
+ metadata on a map entry to make it look like a resource, with the actual
+ retrieval being done with custom code.</p>
+ <p>5) <em>Generation</em>. Deliverance does not have a parser of any kind. It uses
+ XSLT to generate HTML. As noted above, for important parts of usage, no XSLT
+ knowledge is required.</p>
+ <p>Using XSLT gives some benefits:</p>
+ <blockquote>
+ <p>o Extremely optimized.</p>
+ <p>o Extremely documented.</p>
+ <p>o Rich tool chain.</p>
+ <p>o Maintenance burden belongs to others.</p>
+ </blockquote>
+ <p>XSLT has a negative reputation. Thus, Deliverance works hard to allow people to
+ avoid using it, except when they need something custom. For example, navigation
+ boxes don't have to be generated by XSLT, they could be in the HTML lookup up by
+ the CMS and inserted into the theme.</p>
+ </div>
+ <div class="section" id="a-typical-request">
+ <h1>
+ <a name="a-typical-request">A Typical Request</a>
+ </h1>
+ <p>With that background, how does Deliverance work, end-to-end? The following
+ section starts with an Apache restart, finishing with the last byte returned to
+ the browser.</p>
+ <dl class="docutils">
+ <dt><a href="#id3" name="id4">
+ <span class="problematic" id="id4">*</span>
+ </a>Note: This describes how things will be, not how they currently are.</dt>
+ <dd>
+ <p class="last">lxml needs some more work for a couple of things mentioned
+ herein.*</p>
+ </dd>
+ </dl>
+ <p>First, Apache is started. In the conf file, there is a section that maps part of
+ the URL space to a mod_python handler. This handler is part of Deliverance.</p>
+ <p>When the handler module is imported, it performs some one-time optimizations on
+ startup:</p>
+ <p>a. Read the map file, the theme's XHTML, and the site configuration into XML
+ DOMs.</p>
+ <p>b. Read the "blank-compilerdoc" and the compiler stylesheet
+ into a DOM and a processor, respectively.</p>
+ <p>c. Merge everything from (a) into the blank-compilerdoc (later replaced by
+ XInclude).</p>
+ <p>d. Create a compiled theme processor by applying the compiler stylesheet against
+ the blank-compilerdoc. The output is, in fact, another XSLT stylesheet. Namely,
+ it is a "compiled" stylesheet, ready to be applied to each
+ incoming request while doing the least amount of work needed.</p>
+ <p>When a request comes in, Apache passes it off to the Python handler function in
+ Deliverance. The handler takes the relevant part of the URI and does an XPath
+ lookup in the map, grabbing the node referenced by this URI fragment. This map
+ node contains instructions for the next two steps:</p>
+ <blockquote>
+ <p>o Retrieve the contents.</p>
+ <p>o Format the contents.</p>
+ </blockquote>
+ <p>The handler then retrieves the X(H)TML for the contents and applies the compiled
+ stylesheet. The compiled stylesheet has a rule for handling anything unique
+ about that resource type.</p>
+ <p>The results are serialized and returned.</p>
+ </div>
+ <div class="section" id="performance">
+ <h1>
+ <a name="performance">Performance</a>
+ </h1>
+ <p>Since much of the information needed for rendering a requests is statically
+ contained in a specially-tuned, in-memory DOM, performance automatically gets a
+ boost. (This would be the same in Zope.)</p>
+ <p>The use of XSLT, especially compiled into a well-tuned state, gives another big
+ performance win. Many operations, such as drawing a tree or site map, fit the
+ XSLT pattern better than ZPT. Also, libxslt is a much more actively developed
+ project, used by 1,000x the number of people, than ZPT.</p>
+ <p>Memory usage is likely to be an issue. A content map with 400,000 entries could
+ occupy 150 Mb of real memory. However:</p>
+ <blockquote>
+ <p>o Few sites have 400,000 public resources.</p>
+ <p>o Those that do can afford a gigabyte of RAM.</p>
+ </blockquote>
+ <p>For requests that don't require a trip to the CMS, 130 requests/sec should be
+ expected.</p>
+ </div>
+ <div class="section" id="productivity">
+ <h1>
+ <a name="productivity">Productivity</a>
+ </h1>
+ <p>You can speed up a computer by buying a bigger box. How do you speed up a
+ programmer? Unfortunately, Zope has accumulated layers and layer of
+ idiosyncratic frameworks. Some of this is hidden from the integrator and web
+ designer, but some of it peeks through.</p>
+ <p>Deliverance is a massive increase in UI productivity. First and foremost, the
+ entire UI can be developed outside of the CMS, using static models on disk. As
+ long as the CMS returns XML that looks the same as the sample documents and
+ sample content map, everything should just work.</p>
+ <p>Second, this approach gives multiple tools in the toolchain. I like using Oxygen,
+ a cheap but amazing XML/XSLT authoring environment. I can edit the dynamic UI
+ with files on disk, press a button, and see what it will look like when
+ rendered. If there is an error, I get a useful (non-ZPT!) error message, with
+ the cursor sitting on the offending line. I even get a stepwise debugger, where
+ I can watch the output get rendered and set a breakpoint to see the evaluation
+ context.</p>
+ <p>Alternatively, someone can run an xsltproc command like this:</p>
+ <p>xsltproc compiler.xsl blank-compiled.xml | xsltproc - ../tests/sampledoc1.xml</p>
+ <p>...and see what the page will look like. Finally, the simple Python scripts in
+ Deliverance can be run from the command line to process real output in the map.
+ Each part of the process can be inspected to find the offending problem.</p>
+ <p>More generally, the XML+XSLT approach is fundamentally easier. In ZPT, the data
+ model is exposed via baroque, undocumented APIs appearing in TAL expressions. In
+ XML, you just look at the file and visually see the data model. XPath gives a
+ wonderful, simple, but powerful way to manipulate the data model. And although
+ XSLT is baroque, so is the messy pile of deconstructed macros and slots
+ appearing ad-hoc in most large-scale Zope apps.</p>
+ <p>This approach gives other kinds of productivity. For example, there are tons of
+ books, and Google has an answer to every question you might have. Why? Because
+ the installed base of XML and XSLT is four orders of magnitude higher than
+ Zope+CMF+ZPT+[CPS/Plone/Silva].</p>
+ </div>
+
+ </div>
+ </body>
+</html>
Added: z3/deliverance/branches/noappmap/doc/CHANGES.rst
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/doc/CHANGES.rst Mon Jul 31 10:34:19 2006
@@ -0,0 +1,83 @@
+======================
+Changelog
+======================
+
+This document tracks major changes, as well as a TODO list.
+
+TODO
+----
+
+1) I don't know why, but clicking Reload in the browser fails. Basically, the filter seems to be given no data.
+
+
+noapmapp
+--------
+
+This rewrite happened after Rob Miller started using the themes. Below are notes written about the changes.
+
+I decided to refactor everything, to make it simpler and more obvious, and to enable multiple themes. Below are notes on the things I did on branches/noappmap:
+
+1) etc/appmap.xml was changed to etc/thememap.xml
+
+2) The rules are now inline in thememap.xml instead of an XInclude.
+
+3) The structure of that XML is now changed:
+
+ themes
+ theme id="simple"
+ layout (points to HTML file)
+ rules
+ generator (points to themecompiler.xsl)
+ processordoc (the generated XSLT from the layout, rules, and generator)
+
+4) Changed deliverance.py to thememap.py
+
+5) Changed class AppMap to class ThemeMap.
+
+6) Got rid of cruft:
+
+ a. Removed remaining vestiges of my earlier in-memory content map.
+
+ b. No longer use an lxml rule to make the processor. It is now a method.
+
+ c. Removed a bunch of unused files.
+
+ d. Changed the "publish" method to be called "applyTheme".
+
+ e. Removed the handler function in mpfilter.py
+
+7) You can optional pass the filename of the thememap file to the ThemeMap constructor.
+
+8) Parse each theme entry in the thememap.xml into a thememap.themes mapping. This maps themeid to themeprocessor (the generated XSLT processor).
+
+9) The themes were previously being generated using the same XSLT (themecompiler.xsl). This is now a per-theme setting, allowing customization of the processing rules. Later, we can also do some pipeline-ish stuff, such as embedding navigation menus in the generated theme.
+
+10) Added an __str__ for ThemeMap. This lets you see the XML for the whole enchilada:
+
+ a. The original thememap.xml
+
+ b. The HTML for the themes that came in via XInclude.
+
+ c. The XSLT markup used for the theme compiler.
+
+ d. The XSLT markup of the generated theme, to let you debug your XPaths.
+
+11) Added multitheme support. As mentioned above, there is a mapping (thememap.themes) of themeid to themeprocessors. thememap.applyTheme now has an optional argument for the id of the theme. If omitted, it will use the "default" theme, which currently is just the first listed. You can add any of the following to the URL:
+
+ ?theme=simple
+ ?theme=spiral
+ ?theme=default
+ ?theme=notheme
+
+12) mpfilter.py now looks for a "theme" attribute in the request to choose the theme. If not supplied, it is assigned "spiral".
+
+13) Some changes in the outputfilter, though ultimately I don't know if they made a substantive difference. (I *did* remove the calculation of content length...was that needed?)
+
+14) I found the problem with your substitutions. It was my problem, actually...the xpath started with "//", which made it find the wrong theme, once we added two. We should avoid the "//" XPath pattern, now that we have multiple themes in one thememap document.
+
+The XPath is applied relative to the html:html node of the current theme. Thus, I changed those rules to be html:body//html:h1 etc.
+
+15) The spurious xml:base attribute that we got due to XInclude is now manually removed.
+
+16) The files in the doc directory got a little bit of love.
+
Added: z3/deliverance/branches/noappmap/doc/DEBUGGING.rst
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/doc/DEBUGGING.rst Mon Jul 31 10:34:19 2006
@@ -0,0 +1,87 @@
+=====================
+Debugging Deliverance
+=====================
+
+Since it is based on mod_python and lxml, Deliverance gains from its reliance on two well-known quantities (Python and XML technologies). Still, getting all the pieces together can be a bit of a chore. This document provides tips on debugging.
+
+1. Use the command-line first.
+
+Before anything else, run the command-line script and look at the output::
+
+ python ./thememap.py
+
+This will run the `main` function and show the output (plus timing information). If the HTML doesn't look like what you expect, you can fix it without Apache and mod_python being in the way.
+
+
+2. Inspect the thememap.
+
+An instance of the ThemeMap class, for example thememap, contains all the information about the themes in an lxml tree. You can do the following::
+
+ import thememap.
+ thememap = thememap.main()
+ print thememap
+
+The string representation of the instance prints the XML tree (thememap.tree). ThemeMap aggregates the output of each stage into this thememap tree. Thus, printing it shows:
+
+ a. Each theme.
+
+ b. The HTML layout for each theme.
+
+ c. The rules used for each theme.
+
+ d. The XSLT "generator" used to create the final XSLT.
+
+ e. The final XSLT.
+
+Item (e) is the most useful, as discussed next.
+
+
+3. View and edit XSLT.
+
+The XSLT mentioned above can be cut-and-pasted into a file, for example `generatedtheme.xsl`. You can then do a number of debugging steps on that file:
+
+a. Run xmllint on the `generatedtheme.xsl` you just saved to ensure it is well-formed
+XML.
+
+b. Open it in a decent XML-aware editor and ensure the XSLT is "valid".
+
+c. Make sure the generator put XSLT instructions in the places you expected, for example, in the <title>.
+
+d. Look at the XSLT instructions inserted into the theme HTœML and see if the XPaths look correct.
+
+
+4. Play with the XML and XSLT.
+
+This step is the most useful and shows why this approach was taken for Deliverance. Because standard XML technologies are used, you can use a number of tools:
+
+a. Use xsltproc against some of the sample content::
+
+ xsltproc generatedtheme.xsl content/index.html
+
+...and look at the transformation output.
+
+b. Use an XML editor like oXygen to open the XML file (content/index.html) and try debugging the transformation using the XSLT debugger.
+
+c. You can also view the transformation in an XML-aware web browser (IE, FF, Safari, Opera). First, copy content/index.html to content/index.xml (making an XML mime type instead of HTML mime type for the browser.) Next, change the first lines to look like this::
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <?xml-stylesheet href="../tmp/generatedtheme.xsl" type="text/xsl"?>
+
+When you open content/index.xml in a browser, you should see the transformed output.
+
+
+5. Check the XPath statements in the rules.
+
+If you are getting output without error messages, but something (or nothing) is getting substituted into the theme, the cause is usually a bad XPath. The first step is to do (3) above and look at the generated XSLT. Perhaps the XPath in the rule for selecting the theme node didn't work. If an XSLT instruction was put in, perhaps the XPath for selecting content didn't work.
+
+The `getThemeNode` method in ThemeMap has a commented-out line that reports each time a rule finds a theme node. You can uncomment this and run the module again, watching each time a rule finds a place in the theme to generate XSLT instructions.
+
+You can also debug this manually by using lxml::
+
+ from lxml import etree
+ from thememap import nsmap
+ themedoc = etree.ElementTree(file="themes/simple/sampletheme.xml")
+ themedoc.xpath("html:head/html:title", nsmap)
+ contentdoc = etree.ElementTree(file="content/index.html")
+ contentdoc.xpath("html:head/html:title", nsmap)
+
Added: z3/deliverance/branches/noappmap/doc/INSTALL.rst
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/doc/INSTALL.rst Mon Jul 31 10:34:19 2006
@@ -0,0 +1,66 @@
+======================
+Setting up Deliverance
+======================
+
+The whole idea of Deliverance is that it *shouldn't* be a system.
+It's just a thin approach that leverages some serious work being done
+by others. In this case, Deliverance gets most of its value from:
+
+ o Apache. Don't fight it, love it! Yeh, baby!
+
+ o mod_python for both handlers and filters.
+
+ o lxml and thus libxml2/libxslt. This is 90% of the value
+ proposition.
+
+mod_python
+----------
+
+1) Grab mod_python.
+
+2) Make sure you can do this:
+
+ http://www.modpython.org/live/current/doc-html/inst-testing.html
+
+
+lxml
+-----
+
+1) Get 1.0 or later of lxml:
+
+ http://codespeak.net/lxml
+
+2) Make sure you can run some of the tests.
+
+3) Make sure you install it using the same Python used in mod_python.
+ To confirm, put:
+
+ from lxml import etree
+
+...in the mptest.py module used above in the mod_python testing example.
+
+
+Deliverance
+-----------
+
+1) Edit mpfilter.conf and point it to where you put the SVN checkout.
+
+2) In your Apache httpd.conf file, add a line like this::
+
+ Include /Users/me/sandboxes/deliverance/trunk/mpfilter.conf
+ (or wherever is the location of the checkout)
+
+3) Shut Apache down and restart.
+
+4) Keep an eye on the Apache error log::
+
+ tail -f logs/error_log
+
+5) Open a URL like this (or however you have your HTML files pointed to on
+whichever port)::
+
+ http://localhost:9000/sandboxes/deliverance/trunk/
+
+6) If that works, click on the on the "content" directory or go to this URL::
+
+ http://localhost:9000/sandboxes/deliverance/trunk/content/intro.html
Added: z3/deliverance/branches/noappmap/doc/INTRO.rst
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/doc/INTRO.rst Mon Jul 31 10:34:19 2006
@@ -0,0 +1,335 @@
+================================
+Deliverance
+================================
+Content delivery for CMS systems
+--------------------------------
+
+*Note: Work in progress. Some of the ideas, particulary the content
+ map, are in flux.*
+
+CMS systems, particularly in Zope, excel at the structured environment
+of content *production*. This area places a strong emphasis on
+security, workflow, metadata, and other content services.
+
+For content *delivery* on public sites, though, some of this machinery
+is overkill. The framework for content production has a nasty side
+effect of killing performance for content delivery, making reliability
+and debugging a challenge, and forcing other audiences (like web
+designers in charge of look-and-feel) to learn another way to do
+things.
+
+For this reason, many CMS packages make a formal distinction between
+content production and content delivery.
+
+Deliverance is a lightweight, semi-static system for content delivery
+of CMS resources. It runs in mod_python, generating branded pages and
+navigation elements, giving high-performance throughput to anonymous
+visitors. Its primary benefits:
+
+ o High performance
+
+ o Simple re-branding
+
+ o Trusted stack
+
+ o Extreme productivity
+
+It is focused on audiences that want:
+
+ o Predictable delivery to anonymous visitors
+
+ o Some portion of an airgap (logical/physical) between the CMS and
+ the live site
+
+ o Integration with mainstream systems and technologies
+
+This document discusses how the system works, then revisits the
+benefits in detail.
+
+Overview
+---------
+
+Deliverance has two major parts:
+
+ o *Themes*. These apply a consistent look-and-feel to content that streams through
+ Apache. In a nutshell, a theme is an HTML file (plus the CSS, images, etc.)
+ containing boxes that get filled by content.
+
+ o *Content maps*. A description of the content on a site, including metadata and
+ different organization schemes. The content map also has views that, inside
+ Deliverance, can generate HTML for navigation and other purposes.
+
+Each of these can be used without the other, and thus, are discussed separately in the
+following sections.
+
+How The Combination Works
+-------------------------
+
+In a nutshell, Deliverance gets an XML map describing all the published content at a
+point in time. It uses this map to draw navigation elements and issue HTTP requests for
+content of single resources. Finally, a "theme" provides the HTML to return with named
+boxes to be filled by rules.
+
+
+How Themes Work
+---------------
+
+Since a theme is an Apache filter, it can work on content without using the content map
+part. You can apply a theme to content from the filesystem, coming from Zope via
+mod_proxy, or via a Deliverance content map.
+
+Web designers don't want to learn anything new. ZPT tried to embrace this, but by the
+time the ZPT developer has injected all the tal and refactored everything into macros,
+the web designer can't possible continue.
+
+A theme is the corporate identity for a site. It is *not* a template, as it has zero
+stuff in it beyond HTML.
+
+A theme is created by saving the customer's home page and identifying the boxes to be replaced.
+For example, <div id="sitemenu"> identifies a place where a generated menu should go. Web
+designers are familiar with this, as CSS uses such selectors to apply style.
+
+Deliverance has a ruleset that does the merge between the theme file
+and the generated content. In essense, this rule file says: "Find
+'site-menu' in the theme and replace its children with the generated
+contents with an id of 'generated-menu'."
+
+The ruleset is under the control of the integrator, who bridges the
+gap between what the CMS provides and what the UI designer makes
+available. This is done, though, without touching anything on either
+side of the equation.
+
+This allows the theme to be applied to all pages, without touching the
+pages. The theme engine uses XSLT (via lxml) to perform the merge.
+
+
+How Content Maps Work
+---------------------
+
+By design, content delivery is separated from content management. In fact, this
+separation acts as insulation. At various intervals, the CMS makes an "edition" or a
+snapshot of its contents, providing a map with metadata for all the contents that
+should be visible. (In fact, the map could point at a certain *version* of a resource
+that should be visible.)
+
+This map is read by mod_python using lxml. It serves two functions:
+
+a. *Navigation elements*. We can draw site menus and trees without
+visiting the server. Since these can be done in XSLT, not only is the
+performance very good, but we can draw many other kinds of pages. For
+example, we can show all the contents modified in the last week, or
+all the contents in France.
+
+b. *Resource lookup*. The map controls how an incoming, virtual URL
+gets mapped to a real resource. This means the URL space can be
+placeless. Content can appear in multiple places. Equally, content
+from multiple CMSs, even multiple remote hosts, can be integrated into
+the same map.
+
+The identifier used for retrieving the content for the resource can be
+a normal GET or a more complicated QUERY_STRING or even xml-rpc kind
+of lookup.
+
+Note that the contents for many CMS resources are, in fact, very small
+amounts of data. They could be cached inline in the content map and
+not looked up. For frequent pages, this would provide a big win.
+
+Finally, some resources in the map might be virtual, meaning the page
+can be fully rendered in Deliverance. For example, a URL to show all
+the content with the keyword of "CPS" can be serviced without a trip
+to the server. All that is needed is an XSLT rule for generation.
+(Later, the XSLT could be eliminated with a Python extension function
+in lxml.)
+
+
+Architecture
+------------
+
+The goal is high performance. There are certain aspects that never change between requests:
+
+a. The contents of the map.
+
+b. The theme and the rule file for merging.
+
+c. Site configuration, such as site menus.
+
+It makes no sense to re-parse DOMs and stylesheets on each request.
+Equally, it makes no sense to have a multi-stage pipeline when several
+parts never change.
+
+Deliverance gets a tremendous speedup by compiling the theme into a
+stylesheet. It reads the XHTML file for the theme, identifies the
+nodes to be replaced, and generates an XSTL with xsl:value-of and
+xsl:apply-template statements in the right location. Compilation also
+inlines the map data into the XSLT so it doesn't have to included
+later.
+
+Compilation thus gives two benefits:
+
+a. You can re-brand stuff without learning XSLT and without touching
+the HTML of the theme file.
+
+b. Most of the work needed for per-request transformations is done on
+startup. Specifically, we avoid the 50ms hit that the "identity
+transformation" pattern seemed to give.
+
+4) *Retrieval*. mod_python has a Bobo-inspired publisher that walks
+the URL, traversing Python objects using a set of rules.
+
+Deliverance has a similar idea. The URL provides an identifier into
+the map file to retrieve a map item. The map item then gives
+instructions on how to find the content for the page and how to render
+it.
+
+In most cases, some Python code will be issued to retrieve a page from
+the CMS. For this, a very stripped-down skin will be used in the CMS,
+or perhaps no skin at all. For example, the URL in the map file might
+request the DAV view of the resource, thus giving just the data. For
+CMF-based systems, this is a 10x speedup.
+
+In other cases, the map might point to a virtual page, as discussed
+above.
+
+The mapping provides some interesting possibilities for integration.
+First, Deliverance could leverage Apache's infrastructure for
+retrieval and caching. Second, libxml2 has several Python extension
+facilities (XPath functions, custom resolvers) that allow the map to
+act as an integration facility. Simply put some metadata on a map
+entry to make it look like a resource, with the actual retrieval being
+done with custom code.
+
+Deliverance does not have a parser of any kind. It
+uses XSLT to generate HTML. As noted above, for important parts of
+usage, no XSLT knowledge is required.
+
+Using XSLT gives some benefits:
+
+ o Extremely optimized.
+
+ o Extremely documented.
+
+ o Rich tool chain.
+
+ o Maintenance burden belongs to others.
+
+XSLT has a negative reputation. Thus, Deliverance works hard to allow
+people to avoid using it, except when they need something custom. For
+example, navigation boxes don't have to be generated by XSLT, they
+could be in the HTML lookup up by the CMS and inserted into the theme.
+
+A Typical Request
+---------------
+
+With that background, how does Deliverance work, end-to-end? The
+following section starts with an Apache restart, finishing with the
+last byte returned to the browser.
+
+*Note: This describes how things will be, not how they currently are.
+ lxml needs some more work for a couple of things mentioned herein.*
+
+First, Apache is started. In the conf file, there is a section that
+maps part of the URL space to a mod_python handler. This handler is
+part of Deliverance.
+
+When the handler module is imported, it performs some one-time
+optimizations on startup:
+
+a. Read the map file, the theme's XHTML, and the site configuration
+into XML DOMs.
+
+b. Read the "blank-compilerdoc" and the compiler stylesheet into a DOM
+and a processor, respectively.
+
+c. Merge everything from (a) into the blank-compilerdoc (later
+replaced by XInclude).
+
+d. Create a compiled theme processor by applying the compiler
+stylesheet against the blank-compilerdoc. The output is, in fact,
+another XSLT stylesheet. Namely, it is a "compiled" stylesheet, ready
+to be applied to each incoming request while doing the least amount of
+work needed.
+
+When a request comes in, Apache passes it off to the Python handler
+function in Deliverance. The handler takes the relevant part of the
+URI and does an XPath lookup in the map, grabbing the node referenced
+by this URI fragment. This map node contains instructions for the
+next two steps:
+
+ o Retrieve the contents.
+
+ o Format the contents.
+
+The handler then retrieves the X(H)TML for the contents and applies
+the compiled stylesheet. The compiled stylesheet has a rule for
+handling anything unique about that resource type.
+
+The results are serialized and returned.
+
+Performance
+-----------
+
+Since much of the information needed for rendering a requests is
+statically contained in a specially-tuned, in-memory DOM, performance
+automatically gets a boost. (This would be the same in Zope.)
+
+The use of XSLT, especially compiled into a well-tuned state, gives
+another big performance win. Many operations, such as drawing a tree
+or site map, fit the XSLT pattern better than ZPT. Also, libxslt is a
+much more actively developed project, used by 1,000x the number of
+people, than ZPT.
+
+Memory usage is likely to be an issue. A content map with 400,000
+entries could occupy 150 Mb of real memory. However:
+
+ o Few sites have 400,000 public resources.
+
+ o Those that do can afford a gigabyte of RAM.
+
+For requests that don't require a trip to the CMS, 130 requests/sec
+should be expected.
+
+Productivity
+-----------
+
+You can speed up a computer by buying a bigger box. How do you speed
+up a programmer? Unfortunately, Zope has accumulated layers and layer
+of idiosyncratic frameworks. Some of this is hidden from the
+integrator and web designer, but some of it peeks through.
+
+Deliverance is a massive increase in UI productivity. First and
+foremost, the entire UI can be developed outside of the CMS, using
+static models on disk. As long as the CMS returns XML that looks the
+same as the sample documents and sample content map, everything should
+just work.
+
+Second, this approach gives multiple tools in the toolchain. I like
+using Oxygen, a cheap but amazing XML/XSLT authoring environment. I
+can edit the dynamic UI with files on disk, press a button, and see
+what it will look like when rendered. If there is an error, I get a
+useful (non-ZPT!) error message, with the cursor sitting on the
+offending line. I even get a stepwise debugger, where I can watch the
+output get rendered and set a breakpoint to see the evaluation
+context.
+
+Alternatively, someone can run an xsltproc command like this:
+
+xsltproc compiler.xsl blank-compiled.xml | xsltproc - ../tests/sampledoc1.xml
+
+...and see what the page will look like. Finally, the simple Python
+scripts in Deliverance can be run from the command line to process
+real output in the map. Each part of the process can be inspected to
+find the offending problem.
+
+More generally, the XML+XSLT approach is fundamentally easier. In
+ZPT, the data model is exposed via baroque, undocumented APIs
+appearing in TAL expressions. In XML, you just look at the file and
+visually see the data model. XPath gives a wonderful, simple, but
+powerful way to manipulate the data model. And although XSLT is
+baroque, so is the messy pile of deconstructed macros and slots
+appearing ad-hoc in most large-scale Zope apps.
+
+This approach gives other kinds of productivity. For example, there
+are tons of books, and Google has an answer to every question you
+might have. Why? Because the installed base of XML and XSLT is four
+orders of magnitude higher than Zope+CMF+ZPT+[CPS/Plone/Silva].
+
Added: z3/deliverance/branches/noappmap/doc/NOTES.rst
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/doc/NOTES.rst Mon Jul 31 10:34:19 2006
@@ -0,0 +1,43 @@
+===============
+Random Notes
+===============
+
+This file collects random points to weave into other document docs.
+
+0) You can do runtime creation of themes from remote URLs. This is a lot easier than
+you'd think. It could be possible to even build a reasonably smart, productive web
+front end for finding the plug points on each side. (About the only part that would
+take some thinking is URL rewriting for stuff that keeps getting served by another
+host, such as images and CSS.)
+
+1) The mod_python integration is done as a handler rather than a filter. This is just
+historical: In something else, am currently using the module to also resolve certain
+URLs that are managed in an XML "map".
+
+2) For the XML "map" stuff, xml:id support is what makes it so fast. However, this
+imposes some limitations. For example, you can't have slashes in xml:id values.
+
+3) Yeh, it doesn't have tests, other than the timeit function at the bottom
+of deliverance.py. I'm not yet much of a programmer. I hope to fix this deficiency
+during downtime in July.
+
+4) Neat point: Because of XInclude, the appmap XML document has everything it
+needs, including the generated stuff, in a view-source friendly format. Want to
+see what's happening? Just dump the XML document and look at it.
+
+5) The theme doesn't have to be well-formed XML. The HTMLParser can handle garbage as
+input and generate well-formed (though perhaps not valid) stuff on output.
+
+6) The append rule in etc/themerules.xml shows that you can easily copy page-specific
+CSS, JS, etc. from the content document's <head> into the resulting <head>.
+
+7) Extensibility is provided through XML namespaces and lxml's namespace binding
+support. Want a new rule? Just add it and bind a Python handler to it.
+
+8) The "compilation" step provides a nice opportunity to accomplish two goals:
+
+a. Make things simple. Deliverance doesn't expose XSLT to users. Other things
+can be hidden as well.
+
+b. Optimize. If there are calculations that are dynamic, but only calculated
+once, they can be moved into this little pipeline.
Added: z3/deliverance/branches/noappmap/doc/NewWorld.rst
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/doc/NewWorld.rst Mon Jul 31 10:34:19 2006
@@ -0,0 +1,539 @@
+============================================================
+NewWorld Template Machinery
+============================================================
+------------------------------------------------------------
+Analysis of current skinning and proposal for a new approach
+------------------------------------------------------------
+
+
+Plone has accumulated a baroque stack of templating and skinning
+approaches with plans for adding more.
+
+This document analyzes the current issues and makes recommendations
+with working code for new approaches. The specific focus is on how
+the UI consultant and the component consultant accomplish their jobs
+both individually and together, and throughout a project.
+
+
+Caveat
+------
+
+ZPT started with a core vision: improve workflow by letting HTML/XHTML
+authors work with their tools. If you don't care about this vision,
+and think ZPT is for developers, then you won't care about this
+proposal.
+
+
+Summary
+-------
+
+ o The UI consultant's job needs to become more productive, more
+ joyful
+
+ o Plone needs a distinct, formal concept of themes
+
+
+Glossary
+--------
+
+ o UI consulting. At a minimum, drawing pixels on browser screens.
+ Beyond that, collecting what needs to be done (computations,
+ business rules) as stubs to be completed by the component team.
+
+ o Theme. The corporate identity artifacts. HTML, CSS, JS, PNG. No
+ templating, no programming.
+
+ o OldWorld. ZPT, skins, view classes, FS templates and TTW stuff.
+
+ o NewWorld. This proposal.
+
+ o o-wrap template. The current approach to corporate id.
+ ``main_template.pt``, which provides stuff that gets pulled into
+ ``folder_contents.pt`` during evaluation.
+
+ o Main template. o-wrap.
+
+ o Context template. ``folder_contents.pt`` etc.
+
+ o Dreamweaverish. A placeholder for any authoring tool, WYSIWYG or not,
+ that structurally processes XHTML and thus increases
+ productivity/quality.
+
+
+The Problem
+-----------
+
+Instead of leading off with a long-winded architecture discussion,
+let's just jump right into specific instances of problems. These are
+issues Plone inherits from its Zope/CMF/AT/Plone stack.
+
+Here we go with a top-ten list of annoyances:
+
+1. Getting a consistent DOCTYPE.
+
+Our first example is small in scope but wonderfully illustrative of
+the challenge.
+
+Correct DOCTYPEs are critical to UI, as IE will trigger quirks mode
+unless all the pages in your site have the correct DOCTYPE. This
+applies to any potential add-ons written by others.
+
+Like other Zope 2/3 systems, Plone's ZPTs have a challenge on this::
+
+ <metal:page define-macro="master"><metal:doctype define-slot="doctype"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></metal:doctype>
+ <metal:block define-slot="top_slot" />
+
+This is the top of `main_template.pt`, the "o-wrap" for Plone. When a
+UI designer wants to structural change the look-and-feel of a Plone
+site, this template is their starting point. ZPTs original goal was
+to look like normal HTML, and this certainly doesn't.
+
+Getting some static text at the top of each template is seemingly a
+small use case. However, the architecture of ZPT makes this into a
+challenge with negative consequences on the subtemplates (e.g. you
+can't define top-level variables that influence the global macro.)
+
+Summary: DOCTYPEs are important. Controlling them turns templates
+into something unusable by UI consultants.
+
+
+2. Validation.
+
+The previous problem was a small detail with large consequences. This
+problem is larger in scale and philosophy.
+
+ZPTs original goal was simple: "Well-formed markup to please
+Dreamweaverish." There's a flaw in this, though.
+
+DOCTYPEs tell parsers what language you are speaking. Externally,
+they tell the browser what grammar to use. Internally, they tell the
+UI consultant's editor what tool to use.
+
+ZPT uses the same file artifact for both purposes. When the ZPT is
+rendered, the non-valid XHTML markup is processed and removed. The
+result fulfills the contract of the DOCTYPE for external use.
+
+However, when Dreamweaverish opens the file, it sees a DOCTYPE for XHTML,
+then a bunch of tal: and metal: stuff that violates that markup. When
+the UI consultant presses the "Validate" button, a hundred errors are
+produced. Worst case, the tool's helpful features (autocomplete,
+etc.) get turned off due to non-conformance.
+
+What are the choices?
+
+ a. Decide validation and tools don't matter and make UI consultants
+ use vi. [wink]
+
+ b. Make a new DTD or XSD/RNG that includes the tal and metal
+ namespaces. Unfortunately, this new declaration gets sent merrily
+ back to the browser, thus breaking the external contract.
+
+ c. Formally split the external stage of processing from the
+ internal.
+
+This proposal will describe (c).
+
+Ultimately, Plone needs to take a stance on the original ZPT premise.
+Does Plone advertise that templates should be usable in HTML tools
+when opened directly from disk? If so, the current situation is
+unacceptible. If not, then the productivity of UI consultants is
+going to be trial-and-error, reload-Zope-and-view.
+
+Summary: Validation is key to improving the quality and productivity
+of the UI consultant. It is also an important part of UI consultant's
+tools. The current processing approach conflates external validation
+and internal validation. Split them.
+
+
+3. link and script in head.
+
+Systems like Plone have some site-wide resources (CSS and JS) that get
+referenced by every page. These references are done by `<link>` and
+`<script>` elements in the `<head>`.
+
+Some pages have per-page needs for CSS and JS. This is problematic.
+It requires a new block-level element in the context template, usually
+something like `<metal:block fill-slot="top_slot">`. The average UI
+consultant, when confronted with this, will:
+
+ a. Wonder what in the world is a metal block.
+
+ b. Wonder why it is appearing in the head.
+
+ c. Get aggravated when the HTML page is no longer valid and none of
+ the CSS and JS is included when viewed from disk.
+
+This is worse for second-order macros like Kupu, that have to fill the
+slot of a slot.
+
+Summary: It is wrong to use in-page, non-HTML constructs to push
+markup from the context template to the o-wrap template.
+
+
+4. Corporate identity.
+
+I've written about this before for the Zope Site Themes. I won't make
+the case again, but I'll describe the solution below.
+
+ http://www.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/SiteThemes
+
+5. Macros and slots.
+
+Quick, what is the set of macros used in CMF? Plone? Zope 3? What
+slots are available? What custom macros and slots do you have in your
+consulting project?
+
+Zope 3 brought "explicit is better than implicit" to software. The UI
+side needs the same thing. But we need ideas on how to avoid
+activities that feel like programming on the UI consulting side, but
+yield the benefits of knowing what is needed and what is available.
+
+Additionally, the connection between the o-wrap and context template
+is too hard-wired, making things brittle. Just like adapters prevent
+changes in one side from affecting the other, we need similar ideas.
+
+6. Customize button.
+
+The CMF skin system was originally designed to let UI consultants
+customize the UI without touching the artifacts they got from the
+"system". Great idea, but with consequences:
+
+ o If you make a one-line markup change ``folder_contents.pt``, you
+ own it. Any updates in the system's template won't be seen.
+
+ o Zope 3 might make this go away.
+
+
+7. Tedious instructions.
+
+In CMF/Plone templates, every `link`, `script`, `a`, `img`, etc. As
+such, each of these gets a `tal:attributes="src:
+{portal_url}/foo.png"` added to it, even though the image src was
+stated on the actual src attribute.
+
+What happens? First, nobody even bothers putting an actual src
+attribute, meaning the original premise of ZPT is thrown out the
+window. Second, the poor UI designer is confronted with this weird
+construct and has to remember, from system to system, whether it is
+`portal_url` or some other magic chant.
+
+This is painful. More importantly, it tosses out the original premise
+of ZPT, which then tosses out Dreamweaverish and the
+productivity/quality gains.
+
+Most importantly, this is just one example of a recurring problem:
+Zope's template processing model doesn't really parse markup. It
+does, but internally as a black box that can't be influenced.
+
+What's needed is a processing model where the job of fixing portal
+URLs, *and similar jobs*, is moved out of the template, but is still
+controlled by the integrators.
+
+Summary: Rewriting attributes and similar constructs breaks
+productivity and highlights a recurring problem.
+
+8. Template metadata "resource forks".
+
+Since ZPTs aren't treated as documents, you can't put metadata in them
+for use in Zope/CMF. To add metadata, developers have to manage a
+separate ".metadata" file.
+
+9. Cleanup.
+
+Let's say you wanted to cleanup the markup produced on your site.
+Perhaps the UI consultant wants to:
+
+ o Ensure common look, as described under "Corporate identity" above.
+
+ o Compress page size by removing space.
+
+ o Improve readability by indentation.
+
+ o Produce valid XHTML.
+
+The current templating system doesn't provide a place in the
+processing to intervene and take such action.
+
+10. Reload.
+
+In debug mode, template changes don't require a reload. That's great!
+Except the official new way is to move all logic to a view class, and
+that doesn't get reloaded. Add a new image via ZCML? Reload.
+
+Such interruptions in "flow" are anathema in the new realm of agile
+frameworks.
+
+
+Values
+------
+
+Now that we have a list of headaches, let's step back and talk about
+the kinds of values that we want to accomplish for UI consulting in
+the future.
+
+1) Plone consulting should be UI driven.
+
+I think most would nod their head patriotically for such a statement.
+But the reality really isn't like this. Most Plone consultant
+projects are component-driven.
+
+If we say this, let's talk about the environment used by UI consulting
+vs. component consulting. The latter is moving towards testing,
+validation, doctests, etc. The former is still a hit-or-miss,
+low-quality environment. If the former is doing the driving...well,
+we want the driver to have the best quality if we hope to avoid
+accidents.
+
+We should analyze this claim. And we should make sure that the
+highest value, beyond all others, is to make Plone projects driven by
+UI consulting. Then, when we evaluate the headaches listed above, we
+simply choose not to accept reasons why the headaches must continue.
+
+Why do we want this? The customer wants the UI. They don't want the
+components. Also, the UI consultants are better with customers. When
+a business rule is captured in the "software", it should be expressed
+in artifacts used by UI consultants and *not* forked into new
+artifacts used by the component team.
+
+Finally, back to hijacking. When the consultants "collaborate" with
+the UI team currently, the result is usually a mess:
+
+ - The ZPTs become unusable for Dreamweaverish nor browser preview.
+
+ - The templates are only meaningful when evaluated by the server,
+ meaning restarts, software dependencies, etc.
+
+ - When stuff breaks on the "trunk", the UI consultants are stuck.
+
+2) Quality.
+
+Let's make quality a part of UI consulting. How can we work in a
+deliberate way and know about the quality of our UI work?
+
+3) Joy.
+
+The UI consultants have a job to do. They are good at it and have a
+way to do it. Let them do the work with fun and joy. A baroque pile
+of "you just gotta figure it out" technologies is not joy.
+
+4) Flow.
+
+Other web frameworks talk about "flow": no interruptions, no alarms,
+no surprises. Stuff makes sense. Refactoring is fun. You know where
+to find things. Can Plone do better on this?
+
+
+Proposal
+--------
+
+We should continue talking about the kinds of things that drive UI
+consultants crazy. Ways that we can move ahead of the competition.
+
+But we can also brainstorm ideas -- simple ones, wild ones -- that
+might improve things. Maybe the wild ones will inspire the final
+ones.
+
+1) Themes.
+
+The Site Themes proposal (and related work) goes into detail on this.
+Plone 3 *must* split the corporate id part (themes) from the dynamic
+generation part (skins or templates).
+
+ o When you make a Plone site look like your own, you shouldn't touch
+ the same artifacts as the "software".
+
+ o You shouldn't see anything that looks like software
+ (metal:define-slot etc.)
+
+ o Your artifacts should still be well-formed and *valid* in both
+ your editor and browser
+
+...and a host of other reasons defined in the Site Thems URL:
+
+ http://www.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/SiteThemes
+
+How might this work in practice?
+
+a. Save a pile of XHTML, CSS, JS, PNG to disk.
+
+b. Edit a rule file that tells Plone how to fill in boxes with dynamic
+stuff.
+
+c. Nothing in your HTML changes.
+
+d. The output of the ZPT etc. is the input to the theme.
+
+e. There are no macros or slots used to setup DOCTYPEs or specify
+which boxes to fill.
+
+f. You can run a 100 line command-line script to do the merging. (Or
+a CGI script, or lots of other things.)
+
+g. You can analyze your pile of context templates to see if they have
+the identifiers needed for filling in boxes.
+
+h. If something breaks, the template still renders, but without the
+broken box getting filled.
+
+i. Dreamweaver, nxml-mode, etc. can still validate your corporate id.
+
+j. We can use off-the-shelf parsers etc. to implement the connection
+between context output and theme input.
+
+k. We don't have matching macro/slot declarations on each side that
+are easy to break. The rule file controls what matches with what
+(probably with XPath).
+
+l. Based on the previous point, refactoring becomes fun again.
+
+m. The component people rejoice because their templates no longer have
+any connection to styling. No slot filling, etc.
+
+
+2) New approaches to templating.
+
+Although I have code for the former, I'm still in progress on the
+following sections. Since that makes it science fiction, I will
+provided bullets with "imagine if"-style explanations.
+
+a. Meaningful error messages. Imagine that, as you worked on your UI
+consulting, mistakes (yours or others) produced useful error messages.
+Even better, imagine that you felt you could jump in and isolate the
+error. Egads, even fix it.
+
+Also, imagine if the "system" was isolated from your part. You know
+what "the system" is supposed to hand you. You can prove if "the
+system" did or didn't, and thus, whether the problem is in the UI
+consulting layer.
+
+b. Meaningful templates. Imagine if the information in the template
+could be used by the system. For example, a ``<link rel="next"
+href="foo.html"/>`` could be used by the view class or other parts of
+the processing chain.
+
+This point has a LOT of potential. Once the template becomes a useful
+artifact, rather than tag soup parsed into a "proprietary" parse
+format, we can let the system's templates (written by competent
+component consultants) encode more meaning.
+
+c. What drew the pixel? Imagine you could look at a rendered, dynamic
+page, and could find out what "instructions" were responsible for each
+pixel. That alone would make NewWorld discussions worthwhile.
+
+d. Output hacking. Imagine if you could affect every ``<a href="">``
+on the site and, in certain conditions, modify it. Wouldn't that be
+great? Imagine if you could add tag information to the output without
+even *touching* a single "system" artifact, such as a ZPT?
+
+e. Tool support. Imagine if your template language had a schema. You
+could use nxml-mode, oXygen, Dreamweaver, or a host of other tools
+that know how to tell if you screwed up your template. Wouldn't that
+be better than visiting the browser, pressing reload, and deciphering
+a ZPT message?
+
+Really, this point is colossal. People are long used to the benefits
+that smart code editors provide. They provide vast improvements in
+both productivity and quality. They can even help assist you in
+knowing what is possible in the context of something else -- even
+providing tooltips to explain choices.
+
+Beyond that, we can write tests and other tools that process the site
+and see what's going on.
+
+f. Push templates. (Courtesy of Tres.) Imagine a system where a
+template doesn't pull information in by knowing the intricasies of the
+catalog API. Instead, the view class prepares everything that is
+available and pushes it into the template.
+
+With this, the UI consultant could actually master some the Python
+code to assemble static Python dictionaries to be replaced later by
+the component consultants.
+
+g. Testing. Imagine the ongoing process of UI consulting was
+testable. Imagine that, while working on the templates and
+presentation logic, the UI consulting could leave some droppings that
+let made the UI testable. Imagine this was done in a very natural
+way, from the perspective of the UI consultant. It fits their brain,
+so they do it.
+
+h. Documentation. Imagine the same thing were true for documentation.
+UI consultants deal with customers. Customers like to know what is
+finished, in progress, and just started. They like to know how the UI
+plugs together, what is the intent, etc.
+
+Components have lots of stuff now for this. UI consultants have
+squat. They generally draw boxes in Illustrator upfront, then
+immediately forget about it, as they become out-of-date.
+
+i. Business rules. Imagine the UI consultant gets to "own" the
+conversation with the customer about business rules. Archetypes
+provides schemas that express constraints in a reasonably-friendly
+fashion. What more can be done like this, and how can this be done
+more in the UI consultant's domain?
+
+Why is this worth discussing? Because the UI consultant is a better
+fit for managing this:
+
+ o Customers like pixels, not code
+
+ o UI consultants are usually more cuddly than component developers
+
+j. Optimization hints. Imagine a templating model that could say,
+"This block doesn't change much." For example, only on restart. Or
+only when another thing changed. Or etc. Currently this is done by
+cache managers, that feel more like code. Let the UI consultant talk
+it over with the customer and leave hints in the templates.
+
+*Note: This is a benefit of splitting out themes from templates. We
+ can then make templates into more of a domain-specific language for
+ UI consulting without freaking out the Dreamweaver-ish people.*
+
+k. Forms and validation. Long discussion, ask Doug Winter.
+
+
+3) Serverless UI consulting.
+
+I'm working on a desktop tool that lets you do server-ish things
+without a server. If it pans out, it has a number of interesting
+possibilities for automating the business of UI consulting, while
+removing many of the headaches.
+
+a. Reload sucks. Imagine you didn't have to do server restarts for
+anything related to UI consulting. But the artifacts you created were
+still used by the component consultants (though not hijacked).
+
+b. Freedom. Imagine you could develop a UI without caring about
+breakage by the component folks. Without even installing a Zope. You
+could sit in front of the customer, do work, and see 0.05 second
+response time without restarts.
+
+c. Validation. Imagine a GUI that tells you when things need fixing.
+That's the beauty of validation and standards. We can have a schema
+for all inputs, intermediary steps, and outputs of UI consulting. We
+can even look at CSS rules, theme rule files, configure.zcml files,
+and more.
+
+d. Refactoring. Want to change a "slot" from foo to bar? Tell the
+tool and it will fix all the artifacts in your site. Want to change a
+CSS class name? Ditto. Rename a template? Find orphaned templates
+or images?
+
+e. Issue tracking. Lots of code editors support leaving XXX comments,
+then seeing a list of what needs to be done. ZPT? Forget about it.
+Imagine you could do this in UI consulting.
+
+o lint-style stuff
+
+ - is input page well-formed? output?
+
+ - valid?
+
+ - where do boxes come from?
+
+ - any templates/resource not in ZCML?
+
+ - vice versa?
+
+ - list all macros/slots/exports in the site, w/ frequency counts
+
+ - list all classes/ids in the site
Added: z3/deliverance/branches/noappmap/etc/thememap.xml
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/etc/thememap.xml Mon Jul 31 10:34:19 2006
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<themes xmlns:xi="http://www.w3.org/2001/XInclude" xmlns="http://www.plone.org/deliverance">
+ <theme themeid="simple">
+ <layout>
+ <xi:include href="../themes/simple/sampletheme.xml"/>
+ </layout>
+ <rules>
+ <replace theme="html:head/html:title" content="/html:html/html:head/html:title"/>
+ <replace theme="html:body//html:h1[@id='pagetitle']"
+ content="/html:html/html:head/html:title"/>
+ <copy theme="html:body//html:div[@id='pagecontent']" content="html:html/html:body/*"/>
+ <append theme="html:head"
+ content="/html:html/html:head/html:link|/html:html/html:head/html:script"/>
+ </rules>
+ <generator>
+ <xi:include href="../themecompiler.xsl"/>
+ </generator>
+ </theme>
+ <theme themeid="spiral">
+ <layout>
+ <xi:include href="../themes/spiral/spiraltheme.html"/>
+ </layout>
+ <rules>
+ <replace theme="html:head/html:title" content="/html:html/html:head/html:title"/>
+ <replace theme="html:body//html:h1[@id='pagetitle']"
+ content="/html:html/html:head/html:title"/>
+ <copy theme="html:body//html:div[@id='pagecontent']" content="html:html/html:body/*"/>
+ <append theme="html:head"
+ content="/html:html/html:head/html:link|/html:html/html:head/html:script"/>
+ </rules>
+ <generator>
+ <xi:include href="../themecompiler.xsl"/>
+ </generator>
+ </theme>
+</themes>
Added: z3/deliverance/branches/noappmap/mpfilter.conf
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/mpfilter.conf Mon Jul 31 10:34:19 2006
@@ -0,0 +1,11 @@
+# Use an Include directive in your main Apache conf file to
+# add these configuration instructions to your Apache.
+
+
+LoadModule python_module modules/mod_python.so
+
+<Directory /Users/paul/sandboxes/z3/deliverance/branches/noappmap>
+ PythonOutputFilter mpfilter DELIVERANCE
+ AddOutputFilter DELIVERANCE .html
+ PythonDebug On
+</Directory>
Added: z3/deliverance/branches/noappmap/mpfilter.py
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/mpfilter.py Mon Jul 31 10:34:19 2006
@@ -0,0 +1,69 @@
+"""
+Deliverance theming for mod_python filters
+
+Deliverance applies a theme to content. This mod_python module acts as an
+Apache "filter", transforming content as it passes through Apache.
+
+This module gets imported by mod_python during its startup. Thus, the
+thememap instance becomes a global, computed only once. If you need to
+recompute the theme, for example, restart the Apache.
+"""
+from cStringIO import StringIO
+
+from mod_python import apache
+from thememap import ThemeMap
+thememap = ThemeMap() # Themes are generated once at module import time
+
+
+def outputfilter(filter):
+
+ if (filter.req.main or
+ not filter.req.content_type == "text/html"):
+
+ # Presence of filter.req.main tells us that
+ # we are in a subrequest. We don't want to theme
+ # the data more than once, so we pass_on() in
+ # subrequests. We also pass_on() if the the content-type
+ # isn't text/html.
+
+ filter.pass_on()
+
+ # Theme switching
+ # Look in the request arguments for a named theme
+ if not hasattr(filter.req, 'theme'):
+ # Check for a flag to not apply theme
+ args = filter.req.args
+ if args and args.find("theme") > -1:
+ # XXX need a better arg parser here
+ filter.req.theme = args.split("=")[1]
+ else:
+ filter.req.theme = "default"
+
+ # If notheme, stop processing
+ if filter.req.theme == "notheme":
+ filter.pass_on()
+
+ # Create stream buffer
+ # Since the filter might be called multiple times, create
+ # a place to hold content as it gets accumulated from chunks.
+ try:
+ streambuffer = filter.req.streambuffer
+ except AttributeError:
+ filter.req.streambuffer = StringIO()
+ streambuffer = filter.req.streambuffer
+
+ # Read in the content available in the filter and add
+ # it to that read earlier
+ buff = filter.read()
+ while buff:
+ streambuffer.write(buff)
+ buff = filter.read()
+
+ if buff is None:
+ # Looks like the request is finished and this is the
+ # last call by Apache into this filter.
+ themeid = filter.req.theme
+ xmlstring = streambuffer.getvalue()
+ output = thememap.applyTheme(xmlstring, themeid)
+ filter.write(output)
+ filter.close()
Added: z3/deliverance/branches/noappmap/themecompiler.xsl
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themecompiler.xsl Mon Jul 31 10:34:19 2006
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml"
+ exclude-result-prefixes="html" version="1.0">
+ <!-- Theme compiler. Applied to the rule file to generate
+ an XSLT that gets applied to content. -->
+ <xsl:output indent="yes" method="xml"/>
+ <xsl:template match="/">
+ <!-- The compiled theme gets shoved in here -->
+ </xsl:template>
+ <xsl:template match="node()|@*">
+ <xsl:copy>
+ <xsl:apply-templates select="node()|@*"/>
+ </xsl:copy>
+ </xsl:template>
+</xsl:stylesheet>
Added: z3/deliverance/branches/noappmap/thememap.py
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/thememap.py Mon Jul 31 10:34:19 2006
@@ -0,0 +1,195 @@
+"""
+Generating XSLT processors from HTML themes and rule files.
+
+A Deliverance thememap takes an XML configuration file (theme map)
+and 'compiles' one or more themes. The configuration file specifies
+each theme, the file with the layout for that theme, the rule file
+governing how content will be merged into that theme, and the
+'compiler' used to build the theme.
+
+The result is a mapping of theme ids to XSLT processors. The
+XSLT processors contain no lxml-specific instructions. They
+could be printed to a file and applied via xsltproc or included
+in browser-side transformations.
+
+The rules in the rulefile are paired with lxml namespace bindings.
+Each rule thus has a Python class that implements the rule
+behavior. This allows the rules to be extended to cover custom
+uses.
+
+"""
+import os, copy
+from lxml import etree
+from time import time
+from lxml.etree import Namespace, ElementBase
+
+nsmap = {
+ "dv": "http://www.plone.org/deliverance",
+ "html": "http://www.w3.org/1999/xhtml",
+ "xsl": "http://www.w3.org/1999/XSL/Transform",
+ }
+xmlbase = "{http://www.w3.org/XML/1998/namespace}base"
+
+class ThemeMap:
+
+ def __init__(self, thememapfn=None):
+
+ # Open the themes config file, make a tree, and process XIncludes
+ self.module_dir = os.path.dirname(os.path.abspath(__file__))
+ if not thememapfn:
+ # Use a default thememap XML file
+ thememapfn = os.path.join(self.module_dir, "etc/thememap.xml")
+ self.tree = etree.ElementTree(file=thememapfn)
+ self.tree.xinclude()
+
+ # Make a mapping for each theme, allowing us to choose from more
+ # than one theme. The key is the id attribute for the theme and
+ # the value is the generated XSLT processor, made from the rule
+ # file for that theme.
+ self.themes = {}
+ themenodes = self.tree.xpath("dv:theme", nsmap)
+ for themenode in themenodes:
+ themeid = themenode.get("themeid")
+ themeprocessor = self.makeProcessor(themenode)
+ self.themes[themeid] = themeprocessor
+ self.defaulttheme = themenodes[0].get("themeid")
+
+
+ def makeProcessor(self, themenode):
+ """Make XSLT processor by changing theme based on rules"""
+
+ # First make a new <processordoc> that will hold the markup
+ # for the XSLT built from the HTML theme, the rules, and
+ # the generator XSLT. We can then visually inspect the
+ # results of theme generation.
+ processordoc = etree.SubElement(themenode,
+ "{%s}processordoc" % nsmap['dv'])
+
+ # Second, make a copy of the generator XSLT and insert it into
+ # the processordoc node.
+ generatorroot = themenode.xpath("dv:generator/xsl:stylesheet",
+ nsmap)[0]
+ processorroot = copy.deepcopy(generatorroot)
+ processordoc.append(processorroot)
+
+ # Third, take the HTML from the layout and shove it into the
+ # XSLT generator (and remove stray xml:base attribute)
+ themeroot = themenode.xpath("dv:layout/html:html", nsmap)[0]
+ del themeroot.attrib[xmlbase]
+ target = processorroot.xpath("xsl:template[@match='/']", nsmap)[0]
+ target.append(copy.deepcopy(themeroot))
+
+ # Now apply the rules by calling the "apply" method that
+ # was bound via lxml's namespace bindings (defined below)
+ for rule in themenode.xpath("dv:rules/*", nsmap):
+ rule.apply()
+
+ # Create and return an XSLT processor
+ return etree.XSLT(processorroot)
+
+
+ def applyTheme(self, xmlstring, themeid="default"):
+ """Given a string of XML, theme it"""
+
+ if themeid=="default":
+ themeid = self.defaulttheme
+ resource = etree.XML(xmlstring)
+ themeprocessor = self.themes[themeid]
+ response = str(themeprocessor(resource))
+
+ return response
+
+
+ def __str__(self):
+ return etree.tostring(self.tree)
+
+
+# The following are extensions based on lxml namespace extensions. It
+# adds Python behavior to XML nodes. Based on this, you can customize
+# the ruleset for controlling the merge.
+
+class DVRuleBase(ElementBase):
+
+ def getThemeNode(self):
+ """Get a node in the theme doc"""
+
+ # We want to modify the theme HTML that was copied into
+ # the <processordoc>
+ proot = self.xpath("../../dv:processordoc", nsmap)[0]
+ phtmlroot = proot.xpath("xsl:stylesheet/xsl:template/html:html",
+ nsmap)[0]
+
+ # Starting at the processor's html root (phtmlroot), grab
+ # the theme node pointed to by this rule's "theme" attribute.
+ themexpath = self.get("theme")
+ try:
+ themenode = phtmlroot.xpath(themexpath, nsmap)[0]
+ #print "Found themenode", themenode, "for rule", themexpath
+ except IndexError:
+ msg = "Themedoc has no node at: %s" % themexpath
+ print msg
+ themenode = None
+
+ return themenode
+
+
+class RuleReplaceElement(DVRuleBase):
+
+ def apply(self):
+ themenode = self.getThemeNode()
+ if themenode is None:
+ return
+ del(themenode[:])
+ themenode.text = None
+ xslvalueof = etree.SubElement(themenode,
+ "{%s}value-of" % nsmap["xsl"])
+ xslvalueof.set("select", self.get("content"))
+
+
+class RuleCopyElement(DVRuleBase):
+
+ def apply(self):
+ themenode = self.getThemeNode()
+ if themenode is None:
+ return
+ del(themenode[:])
+ themenode.text = None
+ xslvalueof = etree.SubElement(themenode,
+ "{%s}apply-templates" % nsmap["xsl"])
+ xslvalueof.set("select", self.get("content"))
+
+
+class RuleAppendElement(DVRuleBase):
+
+ def apply(self):
+ themenode = self.getThemeNode()
+ if themenode is None:
+ return
+ xslvalueof = etree.SubElement(themenode,
+ "{%s}apply-templates" % nsmap["xsl"])
+ xslvalueof.set("select", self.get("content"))
+
+
+# Bind Python classes for lxml namespace support. This implements
+# the rules in the rulefile.
+namespace = Namespace(nsmap['dv'])
+namespace['replace'] = RuleReplaceElement
+namespace['copy'] = RuleCopyElement
+namespace['append'] = RuleAppendElement
+
+
+def main():
+ xmlstring = open("content/intro.html").read()
+ thememap = ThemeMap()
+ start = time()
+ iters = 50
+ for i in range(iters):
+ result = thememap.applyTheme(xmlstring, "simple")
+ print result[0:2000]
+ print "*** Average time:", (time() - start) / iters, " ***\n"
+ return thememap
+
+
+if __name__ == "__main__":
+ thememap = main()
+ print thememap
Added: z3/deliverance/branches/noappmap/themes/simple/sampletheme.xml
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themes/simple/sampletheme.xml Mon Jul 31 10:34:19 2006
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Theme Title</title>
+ <link rel="stylesheet" type="text/css" href="../themes/simple/simpletheme.css"/>
+ </head>
+ <body>
+ <div id="siteheader">
+ <h1 id="siteheading">Simple Themed Site</h1>
+ <img id="sitelogo" alt="Banjos"
+ src="http://www.foogle.biz/deliverance_the_movie/deliverance2_guitar.jpg"/>
+ </div>
+ <div id="sitemenu">
+ <ul>
+ <li><a href="index.html?theme=simple">Home</a> (simple theme) | </li>
+ <li><a href="intro.html?theme=simple">About Deliverance</a> (simple theme) | </li>
+ <li><a href="index.html?theme=spiral">Home</a> (spiral theme)| </li>
+ <li><a href="intro.html?theme=spiral">About Deliverance</a> (spiral theme) | </li>
+ <li><a href="index.html?theme=notheme">Home</a> | (no theme)</li>
+ <li><a href="intro.html?theme=notheme">About Deliverance</a> (no theme)</li>
+ </ul>
+ </div>
+ <div id="pageframe">
+ <h1 id="pagetitle">Theme Title</h1>
+
+ <div id="pagecontent">This gets replaced because it is theme content.</div>
+ </div>
+ </body>
+</html>
Added: z3/deliverance/branches/noappmap/themes/simple/simpletheme.css
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themes/simple/simpletheme.css Mon Jul 31 10:34:19 2006
@@ -0,0 +1,35 @@
+
+body {
+ font-size: 0.9em;
+ font-family: Optima, Arial, sans-serif;
+ margin: 0;
+}
+
+#siteheader {
+ height: 110px;
+ background-color:silver;
+ padding: 1em;
+}
+
+#siteheading {
+ float:right;
+}
+
+#sitelogo {
+ height: 100px;
+}
+
+
+#sitemenu li {
+ display:inline;
+ list-style-type:none;
+}
+
+#pageframe {
+ margin-left: 4em;
+ margin-top: 2em;
+}
+
+#pagecontent {
+ margin: 2em;
+}
\ No newline at end of file
Added: z3/deliverance/branches/noappmap/themes/spiral/IE7/filesused.txt
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themes/spiral/IE7/filesused.txt Mon Jul 31 10:34:19 2006
@@ -0,0 +1,36 @@
+Files requested by IE
+
+192.168.0.5 - - [15/Jun/2006:08:51:14 +0200] "GET /projects/soros/OSI/folkswagon
+/folkswagon.html HTTP/1.1" 200 12593
+192.168.0.5 - - [15/Jun/2006:08:51:14 +0200] "GET /projects/soros/OSI/folkswagon
+/IE7/ie7-standard-p.js HTTP/1.1" 200 24828
+192.168.0.5 - - [15/Jun/2006:08:51:14 +0200] "GET /projects/soros/OSI/folkswagon
+/IE7/ie7-quirks.js HTTP/1.1" 200 2304
+192.168.0.5 - - [15/Jun/2006:08:51:15 +0200] "GET /projects/soros/OSI/folkswagon
+/folkswagon.css HTTP/1.1" 200 1721
+192.168.0.5 - - [15/Jun/2006:08:51:15 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-bg.css HTTP/1.1" 200 300
+192.168.0.5 - - [15/Jun/2006:08:51:15 +0200] "GET /projects/soros/OSI/folkswagon
+/IE7/ie7-load.htc HTTP/1.1" 200 98
+192.168.0.5 - - [15/Jun/2006:08:51:15 +0200] "GET /projects/soros/OSI/folkswagon
+/IE7/ie7-load.htc HTTP/1.1" 304 -
+192.168.0.5 - - [15/Jun/2006:08:51:15 +0200] "GET /projects/soros/OSI/folkswagon
+/MochiKit/MochiKit.js HTTP/1.1" 200 142976
+192.168.0.5 - - [15/Jun/2006:08:51:16 +0200] "GET /projects/soros/OSI/folkswagon
+/MochiXML.js HTTP/1.1" 200 3854
+192.168.0.5 - - [15/Jun/2006:08:51:16 +0200] "GET /projects/soros/OSI/folkswagon
+/folkswagon.js HTTP/1.1" 200 1133
+192.168.0.5 - - [15/Jun/2006:08:51:17 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-bg.jpg HTTP/1.1" 304 -
+192.168.0.5 - - [15/Jun/2006:08:51:17 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-fade.jpg HTTP/1.1" 304 -
+192.168.0.5 - - [15/Jun/2006:08:51:17 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-blue.jpg HTTP/1.1" 304 -
+192.168.0.5 - - [15/Jun/2006:08:51:17 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-blue.jpg HTTP/1.1" 304 -
+192.168.0.5 - - [15/Jun/2006:08:51:17 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-blue.jpg HTTP/1.1" 304 -
+192.168.0.5 - - [15/Jun/2006:08:51:17 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-fade.jpg HTTP/1.1" 304 -
+192.168.0.5 - - [15/Jun/2006:08:51:18 +0200] "GET /projects/soros/OSI/folkswagon
+/fwfiles/shell-fade.jpg HTTP/1.1" 304 -
Added: z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-content.htc
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-content.htc Mon Jul 31 10:34:19 2006
@@ -0,0 +1,14 @@
+<html>
+<!--
+ IE7, version 0.9 (alpha) (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+-->
+<head>
+<object id="dummy" width="0" height="0"></object>
+<base id="base">
+<style type="text/css">html,body,img{margin:0;}img{vertical-align:top}#dummy{display:inline}</style>
+<script type="text/javascript">public_description=new function(){var l=false;this.ie7_anon=true;this.load=function(o,c,u){if(l)return;l=true;base.href=o.document.URL;dummy.style.cssText=c;var _0=o.parentElement;var _1=Boolean(dummy.currentStyle.display=="inline");function r(){o.runtimeStyle.width=(_1)?image.offsetWidth:"100%";o.runtimeStyle.height=body.offsetHeight};image.onreadystatechange=function(){if(this.readyState=="complete")_2()};image.src=u;function _2(){function copy(p){try{body.style[p]=_0.currentStyle[p]}catch(i){}};for(var j in body.currentStyle)copy(j);body.style.width="";body.style.height="";body.style.border="none";body.style.padding="0";body.style.margin="0";body.style.textIndent="";body.style.position="static";while(_0&&_0.currentStyle.backgroundColor=="transparent"){_0=_0.parentElement}if(_0)document.body.style.backgroundColor=_0.currentStyle.backgroundColor;body.runtimeStyle.cssText=c;body.runtimeStyle.margin="0";if(_1)body.runtimeStyle.width="";r()}}};</script>
+</head>
+<body><span id="body"><img id="image"></span></body>
+</html>
Added: z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-core.js
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-core.js Mon Jul 31 10:34:19 2006
@@ -0,0 +1,6 @@
+/*
+ IE7, version 0.9 (alpha) (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+*/
+eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('x(!1M.1j)z 6(){1l{1M.1j=8;4 1W=8.2m=z 26;8.O=6(){7"1j 2q 0.9 (5G)"};4 36=/36/.B(42.41.40);4 1G=(36)?6(m){1M.1G(1j+"\\n\\n"+m)}:1W;4 2t=5F.2t.1g(/5E (\\d\\.\\d)/)[1];4 2z=K.5D!="5C";x(/5B/.B(42.41.40)||2t<5||!/^5A/.B(K.1J.2A))7;4 1H=K.39=="1H";4 1t,5z;4 1J=K.1J,2s,3X,17=K.17;4 5y="!";4 22={};4 1u=1C;1j.2m=6(n,s){x(!22[n]){x(1u)1k("s="+2o(s));22[n]=z s()}};4 R=/^[\\w\\.]+[^:]*$/;6 1I(h,p){x(R.B(h))h=(p||"")+h;7 h};6 2e(h,p){h=1I(h,p);7 h.1d(0,h.3n("/")+1)};4 s=K.3Z[K.3Z.y-1];1l{1k(s.3z)}1i(i){}4 1R=2e(s.5x);4 1F;1l{4 l=(5w()>=5)?"5v":"5u";1F=z 5t(l+".5s")}1i(i){}4 2w={};6 2y(h,p){1l{h=1I(h,p);x(!2w[h]){1F.5r("5q",h,1C);1F.5p();x(1F.3Y==0||1F.3Y==5o){2w[h]=1F.5n}}}1i(i){1G("2x [1]: 30 5m 5l "+h)}37{7 2w[h]||""}};4 5k=1I("5j.5i",1R);6 1E(V){x(V!=1L){V.2v=13.16.2v;V.12=13.16.12}7 V};1E.12=6(p,c){x(!p)p={};x(!c)c=p.J;x(c=={}.J)c=z 26("8.2v()");c.Y=z 26("7 8");c.Y.16=z 8.Y;c.Y.16.12(p);c.16=z c.Y;c.Y.16.J=c.16.J=c;c.1r=8;c.12=F.32;c.2u=8.2u;7 c};1E.Y=z 26("7 8");1E.Y.16={J:1E,2v:6(){7 F.32.5h.1r.2k(8,F)},12:6(V){x(8==8.J.16&&8.J.12){7 8.J.Y.16.12(V)}D(4 i 5g V){2K(i){1o"J":1o"O":1o"Y":2X}x(2V V[i]=="6"&&V[i]!=8[i]){V[i].1r=8[i]}8[i]=V[i]}x(V.O!=8.O&&V.O!={}.O){V.O.1r=8.O;8.O=V.O}7 8}};6 13(){};8.13=1E.12({J:13,O:6(){7"[5f "+(8.J.2Z||"5e")+"]"},5d:6(1h){7 8.J==1h||1h.2u(8.J)}});13.2Z="13";13.1r=1L;13.2u=6(1h){1f(1h&&1h.1r!=8)1h=1h.1r;7 3J(1h)};13.Y.1r=1E;2a 8.13;4 3A=13.12({J:6(){8.5c=[];8.1p=[]},1s:1W});x(2t<5.5)1k(2y("Z-5b.3a",1R));4 35=1C;1j.1s=6(){1l{x(35)7;35=1H=1c;2s=K.2s;3X=(2z)?2s:1J;x(1K&&1t)1t.2k();15.2k();1n();1G("1u 5a")}1i(e){1G("2x [2]: "+e.38)}};4 1p=[];6 2C(r){1p.11(r)};6 1n(){H.3P();x(1K&&1t)1t.1n();15.1n();D(4 i=0;i<1p.y;i++)1p[i]()};6 23(){4 E=0,R=1,L=2;4 G=/\\(/g,S=/\\$\\d/,I=/^\\$\\d+$/,T=/([\'"])\\1\\+(.*)\\+\\1\\1$/,3Q=/\\\\./g,Q=/\'/,3W=/\\25[^\\25]*\\25/g;4 1X=8;8.18=6(e,r){x(!r)r="";4 l=(34(2o(e)).1g(G)||"").y+1;x(S.B(r)){x(I.B(r)){r=3e(r.1d(1))-1}1b{4 i=l;4 q=Q.B(34(r))?\'"\':"\'";1f(i)r=r.2S("$"+i--).2p(q+"+a[o+"+i+"]+"+q);r=z 26("a,o","7"+q+r.19(T,"$1")+q)}}3V(e||"/^$/",r,l)};8.1U=6(s){24.y=0;7 3R(3S(s,8.2r).19(z 1Z(1D,8.33?"2I":"g"),3T),8.2r).19(3W,"")};8.59=6(){1D.y=0};4 24=[];4 1D=[];4 3U=6(){7"("+2o(8[E]).1d(1,-1)+")"};1D.O=6(){7 8.2p("|")};6 3V(){F.O=3U;1D[1D.y]=F}6 3T(){x(!F[0])7"";4 i=1,j=0,p;1f(p=1D[j++]){x(F[i]){4 r=p[R];2K(2V r){1o"6":7 r(F,i);1o"58":7 F[r+i]}4 d=(F[i].57(1X.2r)==-1)?"":"\\25"+F[i]+"\\25";7 d+r}1b i+=p[L]}};6 3S(s,e){7 e?s.19(z 1Z("\\\\"+e+"(.)","g"),6(m,c){24[24.y]=c;7 e}):s};6 3R(s,e){4 i=0;7 e?s.19(z 1Z("\\\\"+e,"g"),6(){7 e+(24[i++]||"")}):s};6 34(s){7 s.19(3Q,"")}};23.16={J:23,33:1C,2r:""};13.12(23.16);4 1V=23.12({33:1c});4 H=6(){4 2q="2.0.2";4 C=/\\s*,\\s*/;4 H=6(s,14){1l{4 m=[];4 u=F.32.2Q&&!14;4 b=(14)?(14.J==3G)?14:[14]:[K];4 31=3D(s).2S(C),i;D(i=0;i<31.y;i++){s=2R(31[i]);x(3K&&s.1d(0,3).2p("")==" *#"){s=s.1d(2);14=3H([],b,s[1])}1b 14=b;4 j=0,t,f,a,c="";1f(j<s.y){t=s[j++];f=s[j++];c+=t+f;a="";x(s[j]=="("){1f(s[j++]!=")"&&j<s.y){a+=s[j]}a=a.1d(0,-1);c+="("+a+")"}14=(u&&1P[c])?1P[c]:3F(14,t,f,a);x(u)1P[c]=14}m=m.3t(14)}2a H.30;7 m}1i(e){H.30=e;7[]}};H.O=6(){7"6 H() {\\n [2q "+2q+"]\\n}"};4 1P={};H.2Q=1C;H.3P=6(s){x(s){s=2R(s).2p("");2a 1P[s]}1b 1P={}};4 22={};4 1u=1C;H.2m=6(n,s){x(1u)1k("s="+2o(s));22[n]=z s()};H.Y=6(c){7 c?1k(c):8};4 1B={};4 2n={};4 56={1g:/\\[([\\w-]+(\\|[\\w-]+)?)\\s*(\\W?=)?\\s*([^\\]]*)\\]/};4 55=[];1B[" "]=6(r,f,t,n){4 e,i,j;D(i=0;i<f.y;i++){4 s=2l(f[i],t,n);D(j=0;(e=s[j]);j++){x(1q(e)&&2T(e,n))r.11(e)}}};1B["#"]=6(r,f,i){4 e,j;D(j=0;(e=f[j]);j++)x(e.1a==i)r.11(e)};1B["."]=6(r,f,c){c=z 1Z("(^|\\\\s)"+c+"(\\\\s|$)");4 e,i;D(i=0;(e=f[i]);i++)x(c.B(e.2Z))r.11(e)};1B[":"]=6(r,f,p,a){4 t=2n[p],e,i;x(t)D(i=0;(e=f[i]);i++)x(t(e,a))r.11(e)};2n["21"]=6(e){4 d=2U(e);x(d.2Y)D(4 i=0;i<d.2Y.y;i++){x(d.2Y[i]==e)7 1c}};2n["2N"]=6(e){};4 1q=6(e){7(e&&e.3B==1&&e.2P!="!")?e:1L};4 3N=6(e){1f(e&&(e=e.54)&&!1q(e))2X;7 e};4 2W=6(e){1f(e&&(e=e.53)&&!1q(e))2X;7 e};4 3L=6(e){7 1q(e.3O)||2W(e.3O)};4 52=6(e){7 1q(e.3M)||3N(e.3M)};4 51=6(e){4 c=[];e=3L(e);1f(e){c.11(e);e=2W(e)}7 c};4 3K=1c;4 2O=6(e){4 d=2U(e);7(2V d.3I=="50")?/\\.4Z$/i.B(d.4Y):3J(d.3I=="4X 4W")};4 2U=6(e){7 e.4V||e.K};4 2l=6(e,t){7(t=="*"&&e.1A)?e.1A:e.2l(t)};4 4U=6(e,t,n){x(t=="*")7 1q(e);x(!2T(e,n))7 1C;x(!2O(e))t=t.4T();7 e.2P==t};4 2T=6(e,n){7!n||(n=="*")||(e.4S==n)};4 4R=6(e){7 e.4Q};6 3H(r,f,1a){4 m,i,j;D(i=0;i<f.y;i++){x(m=f[i].1A.4P(1a)){x(m.1a==1a)r.11(m);1b x(m.y!=1L){D(j=0;j<m.y;j++){x(m[j].1a==1a)r.11(m[j])}}}}7 r};x(![].11)3G.16.11=6(){D(4 i=0;i<F.y;i++){8[8.y]=F[i]}7 8.y};4 N=/\\|/;6 3F(14,t,f,a){x(N.B(f)){f=f.2S(N);a=f[0];f=f[1]}4 r=[];x(1B[t]){1B[t](r,14,f,a)}7 r};4 S=/^[^\\s>+~]/;4 3E=/[\\s#.:>+~()@]|[^\\s#.:>+~()@]+/g;6 2R(s){x(S.B(s))s=" "+s;7 s.1g(3E)||[]};4 W=/\\s*([\\s>+~(),]|^|$)\\s*/g;4 I=/([\\s>+~,]|[^(]\\+|^)([#.:@])/g;4 3D=6(s){7 s.19(W,"$1").19(I,"$1*$2")};4 1y={O:6(){7"\'"},1g:/^(\'[^\']*\')|("[^"]*")$/,B:6(s){7 8.1g.B(s)},18:6(s){7 8.B(s)?s:8+s+8},3C:6(s){7 8.B(s)?s.1d(1,-1):s}};4 1N=6(t){7 1y.3C(t)};4 E=/([\\/()[\\]?{}|*+-])/g;6 4O(s){7 s.19(E,"\\\\$1")};1u=1c;7 H}();H.2Q=1c;H.2m("Z",6(){1q=6(e){7(e&&e.3B==1&&e.2P!="!"&&!e.3d)?e:1L}});H.Y("1N=F[1]",3k);4 1K=!H.Y("2O(F[1])",1J);4 2h=":21{Z-21:21}:2N{Z-21:2N}"+(1K?"":"*{4N:0}");4 15=z(3A.12({2F:z 1V,1O:"",1w:"",2L:[],1s:6(){8.2M();8.2g()},2g:6(){15.1Y.X=2h+8.1O+8.1w},3y:6(){4 20=K.2l("1e"),s;D(4 i=20.y-1;(s=20[i]);i--){x(!s.2H&&!s.Z){8.2L.11(s.3z)}}},2k:6(){8.3y();8.2g();z 28("1O");8.3u()},3w:6(e,r){8.2F.18(e,r)},1n:6(){4 R=/3v\\d+/g;4 s=2h.1g(/[{,]/g).y;4 20=s+(8.1O.X.1g(/\\{/g)||"").y;4 3x=8.1Y.4M,r;4 2j,c,2i,e,i,j,k,1a;D(i=s;i<20;i++){r=3x[i];x(r&&(2j=r.1e.X.1g(R))){2i=H(r.4L);x(2i.y)D(j=0;j<2j.y;j++){1a=2j[j];c=15.1p[1a.1d(10)][2];D(k=0;(e=2i[k]);k++){x(e.1v[1a])c(e)}}}}},2C:6(p,t,h,r){t=z 1Z("([{;\\\\s])"+p+"\\\\s*:\\\\s*"+t+"[^;}]*");4 i=8.1p.y;x(r)r=p+":"+r;8.3w(t,6(m,o){7(r?m[o+1]+r:m[o])+";Z-"+m[o].1d(1)+";3v"+i+":1"});8.1p.11(F);7 i},1N:6(s){7 s.X||""},2M:6(){x(1H||!1K)K.2M();1b K.4K("<1e Z=1c></1e>");8.1Y=17[17.y-1];8.1Y.Z=1c;8.1Y.X=2h},3u:6(){D(4 i=0;i<17.y;i++){x(!17[i].Z&&17[i].X){17[i].X=""}}}}));6 28(m){8.1z=m;8.1S();15[m]=8;15.2g()};13.12({J:28,O:6(){7"@1z "+8.1z+"{"+8.X+"}"},1n:1W,1S:6(){8.X="";8.1N();8.3m();8.X=3j(8.X);f={}},1N:6(){4 3r=[].3t(15.2L);4 M=/@1z\\s+([^{]*)\\{([^@]+\\})\\s*\\}/2I;4 A=/\\4J\\b|^$/i,S=/\\4I\\b/i,P=/\\4H\\b/i;6 3q(c,m){2f.v=m;7 c.19(M,2f)};6 2f(4G,m,c){m=2J(m);2K(m){1o"1O":1o"1w":x(m!=2f.v)7"";1o"1A":7 c}7""};6 2J(m){x(A.B(m))7"1A";1b x(S.B(m))7(P.B(m))?"1A":"1O";1b x(P.B(m))7"1w"};4 1X=8;6 2G(s,p,m,l){4 c="";x(!l){m=2J(s.1z);l=0}x(m=="1A"||m==1X.1z){x(l<3){D(4 i=0;i<s.3s.y;i++){c+=2G(s.3s[i],2e(s.2d,p),m,l+1)}}c+=3l(s.2d?3p(s,p):3r.3h()||"");c=3q(c,1X.1z)}7 c};4 f={};6 3p(s,p){4 u=1I(s.2d,p);x(f[u])7"";f[u]=(s.2H)?"":3o(15.1N(s,p),2e(s.2d,p));7 f[u]};4 U=/(4F\\s*\\(\\s*[\'"]?)([\\w\\.]+[^:\\)]*[\'"]?\\))/2I;6 3o(c,p){7 c.19(U,"$1"+p.1d(0,p.3n("/")+1)+"$2")};D(4 i=0;i<17.y;i++){x(!17[i].2H&&!17[i].Z){8.X+=2G(17[i])}}},3m:6(){8.X=15.2F.1U(8.X)},1n:1W});4 1y=H.Y("1y");4 2b=[];6 3l(c){7 1x.1U(2c.1U(c))};6 2E(m,o){7 1y+(2b.11(m[o])-1)+1y};6 3k(v){7 1y.B(v)?1k(2b[1k(v)]):v};4 1x=z 1V;1x.18(/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\//);1x.18(/\'[^\']*\'/,2E);1x.18(/"[^"]*"/,2E);1x.18(/\\s+/," ");1x.18(/@(4E|4D)[^;\\n]+[;\\n]|<!\\-\\-|\\-\\->/);4 2c=z 1V;2c.18(/\\\\\'/,"\\\\4C");2c.18(/\\\\"/,"\\\\4B");4 2D=z 1V;2D.18(/\'(\\d+)\'/,3i);6 3j(c){7 2D.1U(c)};6 3i(m,o){7 2b[m[o+1]]};4 2B=[];6 4A(h){2C(h);1Q(1M,"4z",h)};6 1Q(e,t,h){e.4y(t,h);2B.11(F)};6 3g(e,t,h){1l{e.4x(t,h)}1i(i){}};1Q(1M,"4w",6(){4 h;1f(h=2B.3h()){3g(h[0],h[1],h[2])}});6 4v(h,e,c){x(!h.29)h.29={};x(c)h.29[e.2A]=e;1b 2a h.29[e.2A];7 c};1Q(1M,"4u",6(){x(!15.1w)z 28("1w");15.1w.1n()});4 3f=/^\\d+(4t)?$/i;4 4s=/^\\d+%$/;4 4r=6(e,v){x(3f.B(v))7 3e(v);4 s=e.1e.1m;4 r=e.1T.1m;e.1T.1m=e.1v.1m;e.1e.1m=v||0;v=e.1e.4q;e.1e.1m=s;e.1T.1m=r;7 v};6 4p(t){4 e=K.4o(t||"4n");e.1e.X="3c:4m;4l:0;4k:4j;4i:4h;4g:4f(0 0 0 0);1m:-4e";e.3d=1c;7 e};4 27="Z-";6 4d(e){7 e.1v["Z-3c"]=="4c"};6 4b(e,p){7 e.1v[27+p]||e.1v[p]};6 4a(e,p,v){x(e.1v[27+p]==1L){e.1T[27+p]=e.1v[p]}e.1T[p]=v};6 49(o,c,u){4 t=48(6(){1l{x(!o.1S)7;o.1S(o,c,u);3b(t)}1i(i){3b(t)}},10)};1u=1c;x(2z)1k(2y("Z-47.3a",1R));15.1s();x(1K&&1t)1t.1s();x(1H)1j.1s();1b{1J.46(1I("Z-1S.45",1R));1Q(K,"44",6(){x(K.39=="1H")43(1j.1s,0)})}}1i(e){1G("2x [0]: "+e.38)}37{}};',62,353,'||||var||function|return|this|||||||||||||||||||||||||if|length|new||test||for||arguments||cssQuery||constructor|document||||toString|||||||that||cssText|valueOf|ie7||push|specialize|Common|fr|ie7CSS|prototype|styleSheets|add|replace|id|else|true|slice|style|while|match|klass|catch|IE7|eval|try|left|recalc|case|recalcs|thisElement|ancestor|init|ie7HTML|loaded|currentStyle|print|encoder|Quote|media|all|selectors|false|_0|ICommon|httpRequest|alert|complete|makePath|documentElement|isHTML|null|window|getText|screen|cache|addEventHandler|path|load|runtimeStyle|exec|Parser|DUMMY|self|styleSheet|RegExp|st|link|modules|ParseMaster|_1|x01|Function|_2|StyleSheet|elements|delete|_3|safeString|href|getPath|_4|refresh|HEADER|el|ca|apply|getElementsByTagName|addModule|pseudoClasses|String|join|version|escapeChar|body|appVersion|ancestorOf|inherit|_5|Error|loadFile|quirksMode|uniqueID|_6|addRecalc|decoder|_7|parser|_8|disabled|gi|_9|switch|styles|createStyleSheet|visited|isXML|tagName|caching|_10|split|compareNamespace|getDocument|typeof|nextElementSibling|continue|links|className|error|se|callee|ignoreCase|_11|_12|ie7_debug|finally|description|readyState|js|clearInterval|position|ie7_anon|parseInt|PIXEL|removeEventHandler|pop|_13|decode|getString|_14|parse|lastIndexOf|_15|_16|_17|_18|imports|concat|trash|ie7_recalc|addFix|ru|getInlineStyles|innerHTML|Fix|nodeType|remove|parseSelector|ST|select|Array|_19|mimeType|Boolean|isMSIE|firstElementChild|lastChild|previousElementSibling|firstChild|clearCache|ES|_20|_21|_22|_23|_24|DE|viewport|status|scripts|search|location|top|setTimeout|onreadystatechange|htc|addBehavior|quirks|setInterval|addTimer|setOverrideStyle|getDefinedStyle|fixed|isFixed|9999|rect|clip|none|border|block|display|padding|absolute|object|createElement|createTempElement|pixelLeft|getPixelValue|PERCENT|px|onbeforeprint|register|onunload|detachEvent|attachEvent|onresize|addResize|x22|x27|import|namespace|url|ma|bprint|bscreen|ball|write|selectorText|rules|margin|regEscape|item|innerText|getTextContent|scopeName|toUpperCase|compareTagName|ownerDocument|Document|XML|URL|xml|unknown|childElements|lastElementChild|nextSibling|previousSibling|attributeSelectors|AttributeSelector|indexOf|number|reset|successfully|ie5|fixes|instanceOf|Object|common|in|caller|gif|blank|BLANK_GIF|file|loading|responseText|200|send|GET|open|XMLHTTP|ActiveXObject|Microsoft|Msxml2|ScriptEngineMajorVersion|src|ANON|ie7Layout|ms_|ie7_off|CSS1Compat|compatMode|MSIE|navigator|alpha'.split('|'),0,{}))
Added: z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-css-strict.js
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-css-strict.js Mon Jul 31 10:34:19 2006
@@ -0,0 +1,6 @@
+/*
+ IE7, version 0.9 (alpha) (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+*/
+IE7.addModule("ie7-css-strict",function(){if(!modules["ie7-css2-selectors"])return;StyleSheet.prototype.specialize({parse:function(){this.inherit();var r=[].concat(this.rules);r.sort(ie7CSS.Rule.compare);this.cssText=r.join("\n")},createRule:function(s,c){var m;if(m=s.match(ie7CSS.PseudoElement.MATCH))return new ie7CSS.PseudoElement(m[1],m[2],c);else if(m=s.match(ie7CSS.DynamicRule.MATCH))return new ie7CSS.DynamicRule(s,m[1],m[2],m[3],c);else return new ie7CSS.Rule(s,c)}});ie7CSS.specialize({apply:function(){this.inherit();this.Rule.MATCH=/([^{}]+)(\{[^{}]*\})/g}});ie7CSS.Rule.compare=function(r1,r2){return r1.specificity-r2.specificity};var N=[],I=/#/g,C=/[.:\[]/g,T=/^\w|[\s>+~]\w/g;ie7CSS.Rule.score=function(s){return(s.match(I)||N).length*10000+(s.match(C)||N).length*100+(s.match(T)||N).length};ie7CSS.Rule.simple=function(){return""};ie7CSS.Rule.prototype.specialize({specificity:0,init:function(){this.specificity=ie7CSS.Rule.score(this.selector)}})});
Added: z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-css2-selectors.js
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/noappmap/themes/spiral/IE7/ie7-css2-selectors.js Mon Jul 31 10:34:19 2006
@@ -0,0 +1,6 @@
+/*
+ IE7, version 0.9 (alpha) (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+*/
+IE7.addModule("ie7-css2-selectors",function(){cssQuery.addModule("css-level2",function(){selectors[">"]=function(r,f,t,n){var e,i,j;for(i=0;i<f.length;i++){var s=childElements(f[i]);for(j=0;(e=s[j]);j++)if(compareTagName(e,t,n))r.push(e)}};selectors["+"]=function(r,f,t,n){for(var i=0;i<f.length;i++){var e=nextElementSibling(f[i]);if(e&&compareTagName(e,t,n))r.push(e)}};selectors["@"]=function(r,f,a){var t=attributeSelectors[a].test;var e,i;for(i=0;(e=f[i]);i++)if(t(e))r.push(e)};pseudoClasses["first-child"]=function(e){return!previousElementSibling(e)};pseudoClasses["lang"]=function(e,c){c=new RegExp("^"+c,"i");while(e&&!e.getAttribute("lang"))e=e.parentNode;return e&&c.test(e.getAttribute("lang"))};AttributeSelector.NS_IE=/\\:/g;AttributeSelector.PREFIX="@";AttributeSelector.tests={};AttributeSelector.replace=function(m,a,n,c,v){var k=this.PREFIX+m;if(!attributeSelectors[k]){a=this.create(a,c||"",v||"");attributeSelectors[k]=a;attributeSelectors.push(a)}return attributeSelectors[k].id};AttributeSelector.parse=function(s){s=s.replace(this.NS_IE,"|");var m;while(m=s.match(this.match)){var r=this.replace(m[0],m[1],m[2],m[3],m[4]);s=s.replace(this.match,r)}return s};AttributeSelector.create=function(p,t,v){var a={};a.id=this.PREFIX+attributeSelectors.length;a.name=p;t=this.tests[t];t=t?t(this.getAttribute(p),getText(v)):false;a.test=new Function("e","return "+t);return a};AttributeSelector.getAttribute=function(n){switch(n.toLowerCase()){case"id":return"e.id";case"class":return"e.className";case"for":return"e.htmlFor";case"href":if(isMSIE){return"String((e.outerHTML.match(/href=\\x22?([^\\s\\x22]*)\\x22?/)||[])[1]||'')"}}return"e.getAttribute('"+n.replace(N,":")+"')"};AttributeSelector.tests[""]=function(a){retu