[Checkins] SVN: z3c.layout/trunk/src/z3c/layout/ Added transforms to support special cases where the static template needs mangling.

Malthe Borch mborch at gmail.com
Sun Aug 3 21:45:08 EDT 2008


Log message for revision 89336:
  Added transforms to support special cases where the static template needs mangling.

Changed:
  U   z3c.layout/trunk/src/z3c/layout/README.txt
  U   z3c.layout/trunk/src/z3c/layout/interfaces.py
  U   z3c.layout/trunk/src/z3c/layout/meta.zcml
  U   z3c.layout/trunk/src/z3c/layout/model.py
  U   z3c.layout/trunk/src/z3c/layout/zcml.py

-=-
Modified: z3c.layout/trunk/src/z3c/layout/README.txt
===================================================================
--- z3c.layout/trunk/src/z3c/layout/README.txt	2008-08-04 00:57:46 UTC (rev 89335)
+++ z3c.layout/trunk/src/z3c/layout/README.txt	2008-08-04 01:45:07 UTC (rev 89336)
@@ -149,3 +149,33 @@
       </body>
     </html>
 
+Transforms
+----------
+
+To support special cases where you need to use Python to transform the
+static HTML document at compile time, one or more transforms may be
+defined.
+
+    >>> from z3c.layout.model import Transform
+
+Let's add a transform that adds a language setting to the <html>-tag.
+
+    >>> def set_language(node):
+    ...     node.attrib["lang"] = "en"
+    
+    >>> layout.transforms.add(
+    ...    Transform(set_language))
+
+    >>> layout.parse().getroot().attrib["lang"]
+    'en'
+
+And another transform that assigns a class to the <body>-tag.
+
+    >>> def set_class(node, value):
+    ...     node.attrib["class"] = value
+    
+    >>> layout.transforms.add(
+    ...    Transform(lambda body: set_class(body, "front-page"), ".//body"))
+
+    >>> layout.parse().xpath('.//body')[0].attrib["class"]
+    'front-page'

Modified: z3c.layout/trunk/src/z3c/layout/interfaces.py
===================================================================
--- z3c.layout/trunk/src/z3c/layout/interfaces.py	2008-08-04 00:57:46 UTC (rev 89335)
+++ z3c.layout/trunk/src/z3c/layout/interfaces.py	2008-08-04 01:45:07 UTC (rev 89336)
@@ -41,3 +41,6 @@
         value_type=schema.Object(schema=IRegion),
         required=False)
 
+    def parse():
+        """Parse template using lxml's HTML parser class. Transforms
+        are applied before the tree is returned."""

Modified: z3c.layout/trunk/src/z3c/layout/meta.zcml
===================================================================
--- z3c.layout/trunk/src/z3c/layout/meta.zcml	2008-08-04 00:57:46 UTC (rev 89335)
+++ z3c.layout/trunk/src/z3c/layout/meta.zcml	2008-08-04 01:45:07 UTC (rev 89336)
@@ -3,13 +3,17 @@
       
       <complexDirective
          name="layout"
-         schema=".interfaces.ILayout"
+         schema=".zcml.ILayoutDirective"
          handler=".zcml.LayoutDirective">
         
         <subdirective
            name="region"
-           schema=".interfaces.IRegion" />
-        
+           schema=".zcml.IRegionDirective" />
+
+        <subdirective
+           name="transform"
+           schema=".zcml.ITransformDirective" />
+
     </complexDirective>
       
   </directives>

Modified: z3c.layout/trunk/src/z3c/layout/model.py
===================================================================
--- z3c.layout/trunk/src/z3c/layout/model.py	2008-08-04 00:57:46 UTC (rev 89335)
+++ z3c.layout/trunk/src/z3c/layout/model.py	2008-08-04 01:45:07 UTC (rev 89336)
@@ -11,15 +11,23 @@
 class Layout(object):
     interface.implements(interfaces.ILayout)
 
-    def __init__(self, name, template, resource_path, regions=None):
+    def __init__(self, name, template, resource_path, regions=None, transforms=None):
         self.name = name
         self.template = template
         self.regions = regions or set()
+        self.transforms = transforms or set()
         self.resource_path = resource_path
         
     def parse(self):
         tree = lxml.html.parse(self.template)
+
+        # rebase resources
         utils.rebase(tree, self.resource_path)
+
+        # apply transforms
+        for transform in self.transforms:
+            transform(tree)
+            
         return tree
     
 class Region(object):
@@ -39,3 +47,17 @@
             self.xpath,
             self.mode,
             repr(self.provider))
+
+class Transform(object):
+    def __init__(self, handler, xpath=None):
+        self.handler = handler
+        self.xpath = xpath
+
+    def __call__(self, tree):
+        handler = self.handler
+        
+        if self.xpath:
+            for node in tree.xpath(self.xpath):
+                handler(node)
+        else:
+            handler(tree.getroot())

Modified: z3c.layout/trunk/src/z3c/layout/zcml.py
===================================================================
--- z3c.layout/trunk/src/z3c/layout/zcml.py	2008-08-04 00:57:46 UTC (rev 89335)
+++ z3c.layout/trunk/src/z3c/layout/zcml.py	2008-08-04 01:45:07 UTC (rev 89336)
@@ -1,4 +1,8 @@
+from zope import interface
+from zope import schema
+
 from zope.component import zcml
+from zope.configuration import fields
 from zope.app.publisher.browser import resourcemeta
 
 import interfaces
@@ -7,17 +11,38 @@
 import md5
 import os
 
+class ILayoutDirective(interface.Interface):
+    name = interfaces.ILayout.get('name')
+    template = interfaces.ILayout.get('template')
+    
+class IRegionDirective(interfaces.IRegion):
+    pass
+
+class ITransformDirective(interface.Interface):
+    handler = fields.GlobalObject(
+        title=u"Handler that implements transform",
+        required=True)
+
+    xpath = schema.TextLine(
+        title=u"X-path expression for transform",
+        required=False)
+
 class LayoutDirective(object):
-    def __init__(self, _context, name, template, regions=()):
+    def __init__(self, _context, name, template):
         self._context = _context
         self.name = name
         self.template = template
         self.regions = set()
-
+        self.transforms = set()
+        
     def region(self, _context, *args, **kwargs):
         self.regions.add(
             model.Region(*args, **kwargs))
 
+    def transform(self, _context, *args, **kwargs):
+        self.transforms.add(
+            model.Transform(*args, **kwargs))
+                  
     def __call__(self):
         path, filename = os.path.split(self.template)
 
@@ -27,7 +52,8 @@
         resource_path = '++resource++%s' % resource_name
         
         layout = model.Layout(
-            self.name, self.template, resource_path, self.regions)
+            self.name, self.template, resource_path,
+            self.regions, self.transforms)
 
         # register resource directory
         resourcemeta.resourceDirectory(



More information about the Checkins mailing list