summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 2fde714)
raw | patch | inline | side by side (parent: 2fde714)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 20 Aug 2002 04:35:19 +0000 (04:35 +0000) | ||
committer | richard <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] | patch | blob |
diff --git a/doc/templating.txt b/doc/templating.txt
--- /dev/null
+++ b/doc/templating.txt
@@ -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.
+