1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
|
%TOC% %STARTINCLUDE%
## <a name="TWiki_Templating_System"> TWiki Templating System </a>
We have a need for more advanced template handling. As [[Main/JohnTalintyre]] pointed out in [[CommonHeaderFooterTemplate]] it makes sense to separate the header and footer into one file so that it can be easily altered (or even overloaded by a skin). Also the oops dialog messages are all identical except for a few variables like heading, and so on.
Using external modules like the [[TemplateToolkit]] would be one way to go, but this will add a lot of baggage to TWiki.
### <a name="Needs_of_the_TWiki_templating_sy"> Needs of the TWiki templating system </a>
* Separate common parts into one (or more) base template file(s) and include that from other template files like `view.tmpl`.
* Define common variables like a "|" separator in the base template and use them in other template files
* Define variable text in templates (i.e. `view.tmpl`) and pass them to the base template
### <a name="Functional_Spec"> Functional Spec </a>
I tried to define a simple but powerful solution that can be extended over time. Here we go:
* Special template directives (or preprocessor commands) are embedded in normal templates.
* Use of template directives is optional, templates work without them.
* All template preprocessing is done in `&TWiki::Store::readTemplate()` so that the caller simply gets an expanded template file (the same as before)
* Directives are of form <code>%TMPL:<key>%</code> and <code>%TMPL:<key>\{"attr"\}%</code>.
* Initial set of directives:
* <code>%TMPL:INCLUDE\{"file"\}%</code>: Includes a template file. The usual search path is applied.
* <code>%TMPL:DEF\{"var"\}%</code>: Define a variable. Text between this and the END directive is not returned, but put into a hash for later use.
* <code>%TMPL:END%</code>: Ends variable definition.
* <code>%TMPL:P\{"var"\}%</code>: Prints a previously defined variable.
* New directives can be added over time when needed, i.e. IF-THEN-ELSE.
* Variables live in a global name space, there is no parameter passing.
* Two pass processing, so that you can use a variable before declaring it or after.
* Templates and skins work transparently and interchangeably. You could for example define a new skin just for the header & footer and keep the other template files unchanged.
* **_Note:_** The template directive work only for templates, they do not get processed in topic text.
### <a name="Examples"> Examples </a>
Attached is an example of an oops base template `oopsbase.tmpl` and a example oops dialog `oopstest.tmpl` which is based on the base template. This is not the version that will go into the release, it is just a quick hack.
##### <a name="Base_template_oopsbase_tmpl"> Base template oopsbase.tmpl </a>
The first line declares the delimiter variable called "sep", used to separate multiple link items. The variable can be called anywhere by writing <code>%TMPL:P\{"sep"\}%</code>
**_Note:_** Added a dot to escape rendering of variables, i.e. read <code>**%.WEB%**</code> as <code>**%WEB%**</code>.
<table border="1" cellspacing="0" cellpadding="1">
<tr><td>
<verbatim>
%.TMPL:DEF{"sep"}% | %.TMPL:END%
<html>
<head>
<title> %.WIKITOOLNAME% . %.WEB% . %.TOPIC% %.TMPL:P{"titleaction"}%</title>
<base href="%.SCRIPTURL%/view%.SCRIPTSUFFIX%/%.WEB%/%.TOPIC%">
<meta name="robots" content="noindex">
</head>
<body bgcolor="#FFFFFF">
<table width="100%" border="0" cellpadding="3" cellspacing="0">
<tr>
<td bgcolor="%.WEBBGCOLOR%" rowspan="2" valign="top" width="1%">
<a href="%.WIKIHOMEURL%">
<img src="%.PUBURLPATH%/wikiHome.gif" border="0"></a>
</td>
<td>
<b>%.WIKITOOLNAME% . %.WEB% . </b><font size="+2">
<B>%.TOPIC%</b> %.TMPL:P{"titleaction"}%</font>
</td>
</tr>
<tr bgcolor="%.WEBBGCOLOR%">
<td colspan="2">
%.TMPL:P{"webaction"}%
</td>
</tr>
</table>
--- ++ %.TMPL:P{"heading"}%
%.TMPL:P{"message"}%
<table width="100%" border="0" cellpadding="3" cellspacing="0">
<tr bgcolor="%.WEBBGCOLOR%">
<td valign="top">
Topic <b>%TOPIC%</b> . {
%.TMPL:P{"topicaction"}%
}
</td>
</tr>
</table>
</body>
</verbatim>
</td></tr>
</table >
##### <a name="Test_template_oopstest_tmpl"> Test template oopstest.tmpl </a>
Each oops template basically just defines some variables and includes the base template that does the layout work.
<table border="1" cellpadding="1" cellspacing="0">
<tr>
<td><pre>
%.TMPL:DEF{"titleaction"}% (test =titleaction=) %.TMPL:END%
%.TMPL:DEF{"webaction"}% test =webaction= %.TMPL:END%
%.TMPL:DEF{"heading"}%
Test heading %.TMPL:END%
%.TMPL:DEF{"message"}%
Test =message=. Blah blah blah blah blah blah blah blah blah blah blah...
* Some more blah blah blah blah blah blah blah blah blah blah...
* Param1: %PARAM1%
* Param2: %PARAM2%
* Param3: %PARAM3%
* Param4: %PARAM4%
%.TMPL:END%
%.TMPL:DEF{"topicaction"}%
Test =topicaction=:
[[%.WEB%.%TOPIC%][OK]] %.TMPL:P{"sep"}%
[[%.TWIKIWEB%.TWikiRegistration][Register]] %.TMPL:END%
%.TMPL:INCLUDE{"oopsbase"}%
</pre></td>
</tr>
</table>
##### <a name="Sample_screen_shot_of_oopstest_t"> Sample screen shot of oopstest.tmpl </a>
With URL: <code>**.../bin/oops/Test/TestTopic2?template=oopstest&param1=WebHome&param2=WebNotify**</code>
<table border="1" cellpadding="1" cellspacing="0">
<tr>
<td><img alt="testscreen.gif" height="304" src="%ATTACHURLPATH%/testscreen.gif" width="554" /></td>
</tr>
</table>
### <a name="Comments_and_feedback"> Comments and feedback </a>
... is appreciated.
* The itching factor to put this into the upcoming release is to easy the pending converstion of the templates into XHTML format and to have a more flexible solution for templates and skins.
* Is the terminology OK?
* Is the spec OK?
* Are there any other directives that are needed urgently?
* One drawback by using the directives is that you can only test a template from within TWiki. This is because you don't have a text that has a linear flow when you use TMPL:DEF, TMPL:P and TMPL:INCLUDE.
-- [[Main/PeterThoeny]] - 21 Jul 2001 <br />
Looks pretty good - we have a new intranet web designer who wants to put a standard look onto all our intranet sites, including TWiki, so the ability to define modular templates is of great interest! A few comments:
* It's probably more readable to enforce variables being defined before use, which would avoid need for slower two-pass processing.
* [ [[Main/PeterThoeny]] ] You need two-pass processing because you need to define the "|" separator in the included template onone side, and on the other side define variables for the included template. The processing happens as regex in memory, so there is no mesurable speed penalty.
* It would be nice to simplify the syntax a bit, e.g. not using "" around variable names (they don't really need it, unlike filenames), and not using braces - however, this is not a big deal and there is some merit in keeping consistent with the current TWiki syntax.
* [ [[Main/PeterThoeny]] ] The templating system uses the standard internal TWiki function to parse variable attributes. The "" can be skipped (is possible but is not documented).
* Mixed-case keyword names would be nice, as it would be with the current TWiki variables - although upper case is probably more readable.
Also, see [[VerbatimExpandsVariables]] for my views on making VERBATIM not expand %-variables! Fixing this would make discussions of templates easier.
-- [[Main/RichardDonkin]] - 22 Jul 2001 <br />
Looks good. Can do much more than the [[CommonHeaderFooterTemplate]] approach I proposed. TWiki has a fair bit of embedded HTML in it, it might be possible to replace some of this if the variables defined during template read are made available, possible in a name space that can be overridden by TWiki variables.
If/Then/Else could help keep html in templates rather than in Perl. Is there are way of using Perl for the expression in If without compromising security?
-- [[Main/JohnTalintyre]] - 23 Jul 2001 <br />
This looks great. Just to prove it I coded up our drkw headerfooter [example](%ATTACHURLPATH%/twikitemphfexample) using these directives - it seems to be much more powerful. This exercise did bring a couple of questions/issues to mind:
* TWiki currently has a set of templates that are structured something like...
* skin
* view
* preview
* attach
* rdiff
* search
* rename
* rename
* oops
* test
* attach
* ...
* ...so is it intended for the %INCLUDE directive to be recursive? The current template set would suggest that 2 deep recursion is some kind of minimum (do we need a max?).
* [ [[Main/PeterThoeny]] ] Recursion can be of any depth, however for perforance it is better to include just one.
On a slightly less constructive note :), it strikes me that this kind of "template" programming style results in long lists of declarations in some parts of the source and then the occasional embedded "print" statement buried in the HTML. I was wondering whether we could come up with a more concise syntax that toggles between "code" and "data" - something like:
- HTML -
%<nop>.{
#a comment
use "filename";
$name "value";
$name qq(
valuelineone
valuelinetwo
);
print $name;
}%
- HTML -
and
- HTML - %{print $name}% - HTML -
This example maps fairly closely to the original suggestion:
<table border="1" cellpadding="1" cellspacing="0">
<tr>
<td> This... </td>
<td> becomes... </td>
</tr>
<tr>
<td><code>%<nop>TMPL:DEF{"name"}%value%<nop>TMPL:END%</nop></nop></code></td>
<td><code>%<nop>.{$name value}%</nop></code></td>
</tr>
<tr>
<td><code>%<nop>TMPL:DEF{"name"}%</nop></code></td>
<td><code>%<nop>{$name qq(</nop></code></td>
</tr>
<tr>
<td><code>%<nop>TMPL:END%</nop></code></td>
<td><code>)}%</code></td>
</tr>
<tr>
<td><code>%<nop>TMPL:INCLUDE{"filename"}%</nop></code></td>
<td><code>%<nop>.{use "filename"}%</nop></code></td>
</tr>
</table>
This then lead me to think that doing some kind of pre-parsed `eval{}` of the code inside the toggles may be a very powerful way to quickly extend the reach of the TWiki template system to do things like if/then and regexps. For example, what if we allowed template code to (just) call the functions in Func.pm? [Of course, this would make TWiki templates more locked to perl compared to building a new (XHTML) set of intepreted template tags...]
-- [[Main/SteveRoe]] - 23 Jul 2001 <br />
It's worth noting that Peter's suggested syntax is <code>%TMPL:foo%</code>, i.e. no `'.'` after the `'%'` - the use of `'.'` is purely due to [[VerbatimExpandsVariables]] - please comment there, as I'd like to see this aspect of <VERBATIM> fixed. Hence, your attached example doesn't need to use `'%.'`.
However, in your suggested new syntax, it might be useful to use `'%.'` as the intro sequence, as you have done.
-- [[Main/RichardDonkin]] - 23 Jul 2001 <br />
Thanks - fixed!
-- [[Main/SteveRoe]] - 23 Jul 2001 <br />
Please have a look at the latest templates in the [[TWikiAlphaRelease]]. There is now one master template called `twiki.tmpl` that all other templates include (well, will include when all done). The idea is to define all common parts of the templates in `twiki.tmpl` and simply use that from all other templates.
<table border="1" cellpadding="1" cellspacing="0">
<tr>
<th bgcolor="#99CCCC"><strong>Template variable:</strong></th>
<th bgcolor="#99CCCC"><strong>Defines:</strong></th>
</tr>
<tr>
<td> %<nop>TMPL:DEF{"sep"}% </nop></td>
<td> %TMPL:END% </td>
<td> "|" separator </td>
</tr>
<tr>
<td> %<nop>TMPL:DEF{"htmldoctype"}% </nop></td>
<td> Start of all HTML pages </td>
</tr>
<tr>
<td> %<nop>TMPL:DEF{"standardheader"}% </nop></td>
<td> Standard header (for view, rdiff, ... </td>
</tr>
<tr>
<td> %<nop>TMPL:DEF{"simpleheader"}% </nop></td>
<td> Simple header with reduced links (for edit, attach, oops,...) </td>
</tr>
<tr>
<td> %<nop>TMPL:DEF{"standardfooter"}% </nop></td>
<td> Footer, excluding revision part and copyright part </td>
</tr>
<tr>
<td> %<nop>TMPL:DEF{"oops"}% </nop></td>
<td> Skeleton of oops dialog </td>
</tr>
</table>
I.e. the `preview.tmpl` template is now simply:
<pre>
%<nop>TMPL:INCLUDE{"twiki"}%
%<nop>TMPL:DEF{"titleaction"}% (oops) %<nop>TMPL:END%
%<nop>TMPL:DEF{"webaction"}% *Attention* %<nop>TMPL:END%
%<nop>TMPL:DEF{"heading"}% Topic is not saved yet %<nop>TMPL:END%
%<nop>TMPL:DEF{"message"}%
Please go back in your browser and save the topic. %<nop>TMPL:END%
%<nop>TMPL:DEF{"topicaction"}% %<nop>TMPL:END%
%<nop>TMPL:P{"oops"}%
</nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></pre>
With this it should be possible to create a skin that overloads just the `twiki.tmpl`, i.e. a `twiki.print.tmpl` that redefines the header and footer.
In regards to Steve's idea of toggling between "code" and "data", this is certainly powerful. This is what ASP, JSP and [[TemplateToolkit]] is all about. I do not favor this approach for these reasons:
* Mixing code and presentation is not so good because designers are not programmers and vice versa. I.e. a `$name qq( valuelineone valuelinetwo );` command is harder to grasp for a designer then some simple directives. Better let programmers write plugins and designers write templates.
* Security. It is challenging to ensure that no loop holes are in the system when you eval user specified Perl code.
-- [[Main/PeterThoeny]] - 23 Jul 2001 <br />
I suppose given the recent cvs posts on the mailing list, that this is a bit late, but isn't the whole template mechanism distinct from storing and managing revisions? I kind of see it as:
* TWiki:Store gets the latest revision. (Current file store.pm.)
* TWiki:Tmpl does all variable substition. (New file Template.pm?)
* TWiki:Render converts structured text to (x)html. (Currently subs in TWiki.pm.)
I don't know the TWiki code body well enough to know if this is feasible at this point. Sorry if this is noise at this point.
Just my $.02 worth...
-- [[Main/DavidLeBlanc]] - 23 Jul 2001 <br />
Good feedback David. TWiki currently has a different internal structure for historical reasons, not as simple as you point out. We will change the internal structure of TWiki over time.
-- [[Main/PeterThoeny]] - 24 Jul 2001 <br />
Re Steve's suggested new syntax - I tend to agree with Peter for both usability (by designers, who may not know Perl) and security. I'd particularly like to avoid introducing new security issues - TWiki has some security problems already (see [[SecureSetup]] - it's quite hard to avoid open permissions on all files if you are not the webmaster and don't have root access, because it's hard to manipulate files owned by 'nobody').
-- [[Main/RichardDonkin]] - 24 Jul 2001 <br />
I've been playing with this new templating system. Certainly powerful, but a bit confusing. A few thoughts:
* Change the name of `webaction`
* [ [[Main/PeterThoeny]] - 24 Jul 2001 ] This might be a confusing term for the oops dialogs, but is the correct term for all other templates, e.g. the acions you can do on the current web.
* Move oops template definition from `twiki.tmpl` i.e. try and keep definition of snippets of html separate from whole pages
* [ [[Main/PeterThoeny]] ] I was considering this. Technically it is possible to have two level includes, the first one an <code>%TMPL:INCLUDE\{"oops"\}%</code>, and from `oops.tmpl` an <code>%TMPL:INCLUDE\{"twiki"\}%</code>. I decided to put all in one `twiki.tmpl` file for performance reasons.
* Consider an additional syntax for definition inline with print statement - see example below.
* [ [[Main/PeterThoeny]] ] Your proposed <code>%TMPL:P\{"oops" titleaction="(oops)"\}%</code> syntax is a shorter version of saying <code>%TMPL:DEF\{"titleaction"\}% (oops) %TMPL:END% %TMPL:P\{"oops"\}%</code>. This could be a useful addition.
* Slightly different form for DEF e.g. %TMPL:DEF:xxx\{% ... %\}TMPL:DEF%, as block nature of current form is somewhat hidden, some editors will even help point out missing braces. Could make it even shorted e.g. %xxx\{% ... %\}xxx%
* [ [[Main/PeterThoeny]] ] Questions if we should do it. With the current spec you can indent the text so that you can see the structure visually. Also, there is no nesting possible, so the braces are of questionable value. I opt for the current spec.
* Move copyright information into a footer (might be alternative footers without it)
* [ [[Main/PeterThoeny]] ] This is not so simple with the current layout because there are many differences. View and diff have rev info + copyright info; preview has a colored bar + check boxes + copyright info; edit and other scripts have copyright info only.
`ooptauth.tmpl` currently:
<pre>
%<nop>TMPL:INCLUDE{"twiki"}%
%<nop>TMPL:DEF{"titleaction"}% (oops) %<nop>TMPL:END%
%<nop>TMPL:DEF{"webaction"}% *Attention* %<nop>TMPL:END%
%<nop>TMPL:DEF{"heading"}% Either you need to register or the authentication failed %<nop>TMPL:END%
%<nop>TMPL:DEF{"message"}%
To edit topics on this %WIKITOOLNAME% collaborative web, you must be registered as a user.
<nop>---+++++ If you expected to be logged in at this point:
* Did you type in your login name and password correctly? Remeber, both are case sensitive.
* If you want to try again, back arrow and hit edit again.
* If you have forgotton your password, please contact %WIKIWEBMASTER% who will reset it for you.
* __Note:__ You can also login anonymously as user *TWikiGuest* with password *guest*.
<nop>---+++++ To register as a new user:
* Simply fill out the *[<nop>[%<nop>TWIKIWEB%.TWikiRegistration][TWikiRegistration]]* form.
It only takes a minute.%<nop>TMPL:END%
%<nop>TMPL:DEF{"topicaction"}%
[<nop>[%<nop>WEB%.%TOPIC%][OK]] %<nop>TMPL:P{"sep"}%
[<nop>[%<nop>TWIKIWEB%.TWikiRegistration][Register]] %<nop>TMPL:END%
%<nop>TMPL:P{"oops"}%
</nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></pre>
Suggest changing to:
<pre>
%<nop>TMPL:INCLUDE{"oopsbase"}%
%<nop>TMPL:DEF{"message"}%
To edit topics on this %WIKITOOLNAME% collaborative web, you must be registered as a user.
<nop>---+++++ If you expected to be logged in at this point:
* Did you type in your login name and password correctly? Remeber, both are case sensitive.
* If you want to try again, back arrow and hit edit again.
* If you have forgotton your password, please contact %WIKIWEBMASTER% who will reset it for you.
* __Note:__ You can also login anonymously as user *TWikiGuest* with password *guest*.
<nop>---+++++ To register as a new user:
* Simply fill out the *[<nop>[%<nop>TWIKIWEB%.TWikiRegistration][TWikiRegistration]]* form.
It only takes a minute.%<nop>TMPL:END%
%<nop>TMPL:DEF{"topicaction"}%
[<nop>[%<nop>WEB%.%TOPIC%][OK]] %TMPL:P{"sep"}%
[<nop>[%<nop>TWIKIWEB%.TWikiRegistration][Register]] %<nop>TMPL:END%
%<nop>TMPL:P{"oops" titleaction="(oops)" action="*Attention*"
heading="Either you need to register or the authentication failed"}%
</nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></nop></pre>
-- [[Main/JohnTalintyre]] - 24 Jul 2001 <br />
I guess that the concerns about security and complexity in the templates are valid etc. And I have a lot of respect for the caution not to overengineer this kind of thing. Certainly the controls seem to be very powerful as they are...
...I have now modified all of the templates on Codev to use the new TMPL facility. Hopefully this will save someone else the pain. This uses the standardheader, standardfooter and oops declarations as per the first rev of twiki.tmpl - the results are zipped and [attached](%ATTACHURLPATH%/tmpltemplates.zip) and hopefully can be put into CVS (?) to get everyone jump started on this.
* [ [[Main/PeterThoeny]] - 03 Aug 2001 ] Thanks Steve for the modified template files, saved time! All template files are now updated and in [[TWikiAlphaRelease]].
-- [[Main/SteveRoe]] - 25 Jul 2001 <br />
I'd like to suggest a new template print to be used within the header section of pages e.g. "INHEAD". `twiki.skin.tmpl` could define this to include scripts and style that should not be rendered, and in any case head is the standard place, not body (although this usually seems to work).
-- [[Main/JohnTalintyre]] - 31 Jul 2001 <br />
If I understand you correctly, you would like to have this change (in red) in `twiki.tmpl`:
<pre>
%<nop>TMPL:DEF{"htmldoctype"}%
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
<font color="red">%<nop>TMPL:P{"inhead"}%</nop></font> %<nop>TMPL:END%
</nop></nop></pre>
Is that correct? Where would you define "inhead"?
-- [[Main/PeterThoeny]] - 03 Aug 2001 <br />
Every template that was printing out an html heading would use this. Alternatively, being able to fully escape twiki processing (outside of the <head> section could have a similar effect).
-- [[Main/JohnTalintyre]] - 07 Aug 2001 <br /> -- [[TWiki/MikeMannix]] - 30 Aug 2001
|