Code

templating redesign
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Tue, 20 Aug 2002 04:35:19 +0000 (04:35 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Tue, 20 Aug 2002 04:35:19 +0000 (04:35 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@971 57a73879-2fb5-44c3-a270-3262357dd7e2

doc/templating.txt [new file with mode: 0644]

diff --git a/doc/templating.txt b/doc/templating.txt
new file mode 100644 (file)
index 0000000..d8dedd6
--- /dev/null
@@ -0,0 +1,214 @@
+==========================
+HTML Templating Mechanisms
+==========================
+
+:Version: $Revision: 1.1 $
+
+Current Situation and Issues
+============================
+
+Syntax
+------
+
+Roundup currently uses an element-based HTML-tag-alike templating syntax::
+
+   <display call="checklist('status')">
+
+The templates were initially parsed using recursive regular expression
+parsing, and since no template tag could be encapsulate itself, the parser
+worked just fine. Then we got the ``<require>`` tag, which could have other
+``<require>`` tags inside. This forced us to move towards a more complete
+parser, using the standard python sgmllib/htmllib parser. The downside of this
+switch is that constructs of the form::
+
+   <tr class="row-<display call="plain('status')">">
+
+don't parse as we'd hope. It would be almost impossible to modify the sgmllib
+parser to parse the above "correctly", so a wholly new parser would be
+required. That is a large undertaking, and doesn't address another couple of
+issues that have arisen:
+
+1. the template syntax is neither HTML-editor friendly, not a well-formed
+   syntax for other tools to work with, and
+2. user requirements generally have to be anticipated and accounted for in
+   templating functions (like ``plain()`` and ``checklist()`` above), and
+   we are therefore artificially restrictive.
+
+Arguments for switching templating systems:
+
+*Pros*
+
+  - we can be editor-friendly
+  - more flexibility in templating control and content
+
+*Cons*
+
+  - installed user base (though they'd have to edit their templates with the
+    next release anyway)
+  - current templating system is pretty trivial, and a more flexible system
+    is likely to be more complex
+
+
+Templates
+---------
+
+We should also take this opportunity to open up the fexibility of the
+templates through:
+
+1. allowing the instance to define a "page" template, which holds the overall
+   page structure, including header and footer
+
+
+
+Possible approaches
+===================
+
+Zope's PageTemplates
+--------------------
+
+Using Zope's PageTemplates seems to be the best approach of the lot.
+In my opinion, it's the peak of HTML templating technology at present. With
+appropriate infrastructure, the above two examples would read:
+
+  <span tal:replace="item/status/checklist">status checklist</span>
+
+  <tr tal:attributes="class string:row-${item/status/name}">
+
+... which doesn't look that much more complicated... honest...
+
+Other fun can be had when you start playing with stuff like:
+
+  <table>
+   <tr tal:repeat="message item/msg/list">
+    <td tal:define="from message/from">
+     <a href="" tal:attributes="href string:mailto:${from/address}"
+                tal:content="from/name">mailto link</a>
+    </td>
+    <td tal:content="message/title">subject</td>
+    <td tal:content="message/created">received date</td>
+   </tr>
+  </table>
+
+
+Implementation
+~~~~~~~~~~~~~~
+
+I'm envisaging an infrastructure layer where each template has the following
+variables defined:
+
+*class*
+  the current class of node being displayed
+*item*
+  the current node from the database, if we're viewing a specific node
+(*classname*)
+  the current node is also available under its classname, so a *user* node
+  would also be available under the name *user*.
+*form*
+  the current CGI form information
+*instance*
+  the current instance
+*db*
+  the current open database
+*config*
+  the current instance config
+*util*
+  utility methods
+
+Then accesses through an *item*::
+
+  class HTMLItem:
+    def __getattr__(self, attr):
+        ''' return an HTMLItem instance '''
+    def history(self, ...)
+    def classhelp(self, ...)
+    def remove(self, ...)
+
+String, Number, Date, Interval HTMLProperty
+ a wrapper object which may be stringified for the current plain() behaviour
+ and has methods emulating all the current display functions, so
+ ``item/name/plain`` would emulate the current ``call="plain()``". Also, 
+ ``python:item.name.plain(name=value)`` would work just fine::
+
+   class HTMLProperty:
+     def __init__(self, instance, db, ...)
+     def __str__(self):
+        return self.plain()
+
+   class StringHTMLProperty(HTLProperty):
+     def plain(self, ...)
+     def field(self, ...)
+     def stext(self, ...)
+     def multiline(self, ...)
+     def email(self, ...)
+
+   class NumberHTMLProperty(HTMLProperty):
+     def plain(self, ...)
+     def field(self, ...)
+
+   class BooleanHTMLProperty(HTMLProperty):
+     def plain(self, ...)
+     def field(self, ...)
+
+   class DateHTMLProperty(HTMLProperty):
+     def plain(self, ...)
+     def field(self, ...)
+     def reldate(self, ...)
+
+   class IntervalHTMLProperty(HTMLProperty):
+     def plain(self, ...)
+     def field(self, ...)
+
+Link HTMLProperty
+ the wrapper object would include the above as well as being able to access
+ the class information. Stringifying the object itself would result in the
+ value from the item being displayed. Accessing attributes of this object
+ would result in the appropriate entry from the class being queried for the
+ property accessed (so item/assignedto/name would look up the user entry
+ identified by the assignedto property on item, and then the name property of
+ that user)::
+    
+   class LinkHTMLProperty(HTMLProperty):
+     ''' Be a HTMLItem too '''
+     def __getattr__(self, attr):
+        ''' return a new HTMLProperty '''
+     def download(self, ...)
+     def checklist(self, ...)
+
+Multilink HTMLProperty
+ the wrapper would also be iterable, returning a wrapper object like the Link
+ case for each entry in the multilink::
+
+   class MultilinkHTMLProperty(HTMLProperty):
+     def __len__(self):
+        ''' length of the multilink '''
+     def __getitem(self, num):
+        ''' return a new HTMLItem '''
+     def checklist(self, ...)
+     def list(self, ...)
+*util*
+ the util object will handle::
+
+   class Util:
+     def __init__(self, ...)
+     def filterspec(self, ...)
+     def note(self, ...)
+     def submit(self, ...)
+
+Action
+======
+
+1. Investigate how PageTemplates would be integrated into Roundup:
+
+   - we could go for a fully-divorced-from-Zope approach, which would involve
+     bundling PageTemplates/TAL/ZTUtils in with Roundup, with all the
+     Zope-specific bits removed.
+   - we could try to coexist with a Zope installation, but there the problem
+     would be that Zope includes its own copy of PageTemplates/TAL/ZTUtils and
+     we'd be installing a version in site-packages, which would be bad.
+
+   The latter may allow nicer integration with Zope itself, giving Zope
+   Roundup users access to acquired information in their templates.
+
+2. Implement the Roundup infrastructure detailed in the `implementation`_ above.
+