1 ==========================
2 HTML Templating Mechanisms
3 ==========================
5 :Version: $Revision: 1.1 $
7 Current Situation and Issues
8 ============================
10 Syntax
11 ------
13 Roundup currently uses an element-based HTML-tag-alike templating syntax::
15 <display call="checklist('status')">
17 The templates were initially parsed using recursive regular expression
18 parsing, and since no template tag could be encapsulate itself, the parser
19 worked just fine. Then we got the ``<require>`` tag, which could have other
20 ``<require>`` tags inside. This forced us to move towards a more complete
21 parser, using the standard python sgmllib/htmllib parser. The downside of this
22 switch is that constructs of the form::
24 <tr class="row-<display call="plain('status')">">
26 don't parse as we'd hope. It would be almost impossible to modify the sgmllib
27 parser to parse the above "correctly", so a wholly new parser would be
28 required. That is a large undertaking, and doesn't address another couple of
29 issues that have arisen:
31 1. the template syntax is neither HTML-editor friendly, not a well-formed
32 syntax for other tools to work with, and
33 2. user requirements generally have to be anticipated and accounted for in
34 templating functions (like ``plain()`` and ``checklist()`` above), and
35 we are therefore artificially restrictive.
37 Arguments for switching templating systems:
39 *Pros*
41 - we can be editor-friendly
42 - more flexibility in templating control and content
44 *Cons*
46 - installed user base (though they'd have to edit their templates with the
47 next release anyway)
48 - current templating system is pretty trivial, and a more flexible system
49 is likely to be more complex
52 Templates
53 ---------
55 We should also take this opportunity to open up the fexibility of the
56 templates through:
58 1. allowing the instance to define a "page" template, which holds the overall
59 page structure, including header and footer
63 Possible approaches
64 ===================
66 Zope's PageTemplates
67 --------------------
69 Using Zope's PageTemplates seems to be the best approach of the lot.
70 In my opinion, it's the peak of HTML templating technology at present. With
71 appropriate infrastructure, the above two examples would read:
73 <span tal:replace="item/status/checklist">status checklist</span>
75 <tr tal:attributes="class string:row-${item/status/name}">
77 ... which doesn't look that much more complicated... honest...
79 Other fun can be had when you start playing with stuff like:
81 <table>
82 <tr tal:repeat="message item/msg/list">
83 <td tal:define="from message/from">
84 <a href="" tal:attributes="href string:mailto:${from/address}"
85 tal:content="from/name">mailto link</a>
86 </td>
87 <td tal:content="message/title">subject</td>
88 <td tal:content="message/created">received date</td>
89 </tr>
90 </table>
93 Implementation
94 ~~~~~~~~~~~~~~
96 I'm envisaging an infrastructure layer where each template has the following
97 variables defined:
99 *class*
100 the current class of node being displayed
101 *item*
102 the current node from the database, if we're viewing a specific node
103 (*classname*)
104 the current node is also available under its classname, so a *user* node
105 would also be available under the name *user*.
106 *form*
107 the current CGI form information
108 *instance*
109 the current instance
110 *db*
111 the current open database
112 *config*
113 the current instance config
114 *util*
115 utility methods
117 Then accesses through an *item*::
119 class HTMLItem:
120 def __getattr__(self, attr):
121 ''' return an HTMLItem instance '''
122 def history(self, ...)
123 def classhelp(self, ...)
124 def remove(self, ...)
126 String, Number, Date, Interval HTMLProperty
127 a wrapper object which may be stringified for the current plain() behaviour
128 and has methods emulating all the current display functions, so
129 ``item/name/plain`` would emulate the current ``call="plain()``". Also,
130 ``python:item.name.plain(name=value)`` would work just fine::
132 class HTMLProperty:
133 def __init__(self, instance, db, ...)
134 def __str__(self):
135 return self.plain()
137 class StringHTMLProperty(HTLProperty):
138 def plain(self, ...)
139 def field(self, ...)
140 def stext(self, ...)
141 def multiline(self, ...)
142 def email(self, ...)
144 class NumberHTMLProperty(HTMLProperty):
145 def plain(self, ...)
146 def field(self, ...)
148 class BooleanHTMLProperty(HTMLProperty):
149 def plain(self, ...)
150 def field(self, ...)
152 class DateHTMLProperty(HTMLProperty):
153 def plain(self, ...)
154 def field(self, ...)
155 def reldate(self, ...)
157 class IntervalHTMLProperty(HTMLProperty):
158 def plain(self, ...)
159 def field(self, ...)
161 Link HTMLProperty
162 the wrapper object would include the above as well as being able to access
163 the class information. Stringifying the object itself would result in the
164 value from the item being displayed. Accessing attributes of this object
165 would result in the appropriate entry from the class being queried for the
166 property accessed (so item/assignedto/name would look up the user entry
167 identified by the assignedto property on item, and then the name property of
168 that user)::
170 class LinkHTMLProperty(HTMLProperty):
171 ''' Be a HTMLItem too '''
172 def __getattr__(self, attr):
173 ''' return a new HTMLProperty '''
174 def download(self, ...)
175 def checklist(self, ...)
177 Multilink HTMLProperty
178 the wrapper would also be iterable, returning a wrapper object like the Link
179 case for each entry in the multilink::
181 class MultilinkHTMLProperty(HTMLProperty):
182 def __len__(self):
183 ''' length of the multilink '''
184 def __getitem(self, num):
185 ''' return a new HTMLItem '''
186 def checklist(self, ...)
187 def list(self, ...)
189 *util*
190 the util object will handle::
192 class Util:
193 def __init__(self, ...)
194 def filterspec(self, ...)
195 def note(self, ...)
196 def submit(self, ...)
198 Action
199 ======
201 1. Investigate how PageTemplates would be integrated into Roundup:
203 - we could go for a fully-divorced-from-Zope approach, which would involve
204 bundling PageTemplates/TAL/ZTUtils in with Roundup, with all the
205 Zope-specific bits removed.
206 - we could try to coexist with a Zope installation, but there the problem
207 would be that Zope includes its own copy of PageTemplates/TAL/ZTUtils and
208 we'd be installing a version in site-packages, which would be bad.
210 The latter may allow nicer integration with Zope itself, giving Zope
211 Roundup users access to acquired information in their templates.
213 2. Implement the Roundup infrastructure detailed in the `implementation`_ above.