Skip to content

Commit d724f68

Browse files
author
Richard Jones
committed
templating redesign
1 parent 8938227 commit d724f68

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed

doc/templating.txt

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
==========================
2+
HTML Templating Mechanisms
3+
==========================
4+
5+
:Version: $Revision: 1.1 $
6+
7+
Current Situation and Issues
8+
============================
9+
10+
Syntax
11+
------
12+
13+
Roundup currently uses an element-based HTML-tag-alike templating syntax::
14+
15+
<display call="checklist('status')">
16+
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::
23+
24+
<tr class="row-<display call="plain('status')">">
25+
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:
30+
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.
36+
37+
Arguments for switching templating systems:
38+
39+
*Pros*
40+
41+
- we can be editor-friendly
42+
- more flexibility in templating control and content
43+
44+
*Cons*
45+
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
50+
51+
52+
Templates
53+
---------
54+
55+
We should also take this opportunity to open up the fexibility of the
56+
templates through:
57+
58+
1. allowing the instance to define a "page" template, which holds the overall
59+
page structure, including header and footer
60+
61+
62+
63+
Possible approaches
64+
===================
65+
66+
Zope's PageTemplates
67+
--------------------
68+
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:
72+
73+
<span tal:replace="item/status/checklist">status checklist</span>
74+
75+
<tr tal:attributes="class string:row-${item/status/name}">
76+
77+
... which doesn't look that much more complicated... honest...
78+
79+
Other fun can be had when you start playing with stuff like:
80+
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>
91+
92+
93+
Implementation
94+
~~~~~~~~~~~~~~
95+
96+
I'm envisaging an infrastructure layer where each template has the following
97+
variables defined:
98+
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
116+
117+
Then accesses through an *item*::
118+
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, ...)
125+
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::
131+
132+
class HTMLProperty:
133+
def __init__(self, instance, db, ...)
134+
def __str__(self):
135+
return self.plain()
136+
137+
class StringHTMLProperty(HTLProperty):
138+
def plain(self, ...)
139+
def field(self, ...)
140+
def stext(self, ...)
141+
def multiline(self, ...)
142+
def email(self, ...)
143+
144+
class NumberHTMLProperty(HTMLProperty):
145+
def plain(self, ...)
146+
def field(self, ...)
147+
148+
class BooleanHTMLProperty(HTMLProperty):
149+
def plain(self, ...)
150+
def field(self, ...)
151+
152+
class DateHTMLProperty(HTMLProperty):
153+
def plain(self, ...)
154+
def field(self, ...)
155+
def reldate(self, ...)
156+
157+
class IntervalHTMLProperty(HTMLProperty):
158+
def plain(self, ...)
159+
def field(self, ...)
160+
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)::
169+
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, ...)
176+
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::
180+
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, ...)
188+
189+
*util*
190+
the util object will handle::
191+
192+
class Util:
193+
def __init__(self, ...)
194+
def filterspec(self, ...)
195+
def note(self, ...)
196+
def submit(self, ...)
197+
198+
Action
199+
======
200+
201+
1. Investigate how PageTemplates would be integrated into Roundup:
202+
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.
209+
210+
The latter may allow nicer integration with Zope itself, giving Zope
211+
Roundup users access to acquired information in their templates.
212+
213+
2. Implement the Roundup infrastructure detailed in the `implementation`_ above.
214+

0 commit comments

Comments
 (0)