%TOC% %STARTINCLUDE% ## TWiki Templating System 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. ### Needs of the TWiki templating system * 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 ### Functional Spec 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 %TMPL:<key>% and %TMPL:<key>\{"attr"\}%. * Initial set of directives: * %TMPL:INCLUDE\{"file"\}%: Includes a template file. The usual search path is applied. * %TMPL:DEF\{"var"\}%: Define a variable. Text between this and the END directive is not returned, but put into a hash for later use. * %TMPL:END%: Ends variable definition. * %TMPL:P\{"var"\}%: 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. ### Examples 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. ##### Base template oopsbase.tmpl The first line declares the delimiter variable called "sep", used to separate multiple link items. The variable can be called anywhere by writing %TMPL:P\{"sep"\}% **_Note:_** Added a dot to escape rendering of variables, i.e. read **%.WEB%** as **%WEB%**.
%.TMPL:DEF{"sep"}% | %.TMPL:END% %.WIKITOOLNAME% . %.WEB% . %.TOPIC% %.TMPL:P{"titleaction"}%
%.WIKITOOLNAME% . %.WEB% . %.TOPIC% %.TMPL:P{"titleaction"}%
%.TMPL:P{"webaction"}%
--- ++ %.TMPL:P{"heading"}% %.TMPL:P{"message"}%
Topic %TOPIC% . { %.TMPL:P{"topicaction"}% }
##### Test template oopstest.tmpl Each oops template basically just defines some variables and includes the base template that does the layout work.
%.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"}%
##### Sample screen shot of oopstest.tmpl With URL: **.../bin/oops/Test/TestTopic2?template=oopstest&param1=WebHome&param2=WebNotify**
testscreen.gif
### Comments and feedback ... 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
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
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
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 - %.{ #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:
This... becomes...
%TMPL:DEF{"name"}%value%TMPL:END% %.{$name value}%
%TMPL:DEF{"name"}% %{$name qq(
%TMPL:END% )}%
%TMPL:INCLUDE{"filename"}% %.{use "filename"}%
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
It's worth noting that Peter's suggested syntax is %TMPL:foo%, 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
Thanks - fixed! -- [[Main/SteveRoe]] - 23 Jul 2001
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.
Template variable: Defines:
%TMPL:DEF{"sep"}% %TMPL:END% "|" separator
%TMPL:DEF{"htmldoctype"}% Start of all HTML pages
%TMPL:DEF{"standardheader"}% Standard header (for view, rdiff, ...
%TMPL:DEF{"simpleheader"}% Simple header with reduced links (for edit, attach, oops,...)
%TMPL:DEF{"standardfooter"}% Footer, excluding revision part and copyright part
%TMPL:DEF{"oops"}% Skeleton of oops dialog
I.e. the `preview.tmpl` template is now simply:
%TMPL:INCLUDE{"twiki"}%
%TMPL:DEF{"titleaction"}% (oops) %TMPL:END%
%TMPL:DEF{"webaction"}% *Attention* %TMPL:END%
%TMPL:DEF{"heading"}% Topic is not saved yet %TMPL:END%
%TMPL:DEF{"message"}%
  Please go back in your browser and save the topic. %TMPL:END%
%TMPL:DEF{"topicaction"}% %TMPL:END%
%TMPL:P{"oops"}%
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
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
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
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
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 %TMPL:INCLUDE\{"oops"\}%, and from `oops.tmpl` an %TMPL:INCLUDE\{"twiki"\}%. 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 %TMPL:P\{"oops" titleaction="(oops)"\}% syntax is a shorter version of saying %TMPL:DEF\{"titleaction"\}% (oops) %TMPL:END% %TMPL:P\{"oops"\}%. 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:
%TMPL:INCLUDE{"twiki"}%
%TMPL:DEF{"titleaction"}% (oops) %TMPL:END%
%TMPL:DEF{"webaction"}% *Attention* %TMPL:END%
%TMPL:DEF{"heading"}% Either you need to register or the authentication failed %TMPL:END%
%TMPL:DEF{"message"}%

To edit topics on this %WIKITOOLNAME% collaborative web, you must be registered as a user.

---+++++ 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*.

---+++++ To register as a new user:

   * Simply fill out the *[[%TWIKIWEB%.TWikiRegistration][TWikiRegistration]]* form.
     It only takes a minute.%TMPL:END%
%TMPL:DEF{"topicaction"}%
[[%WEB%.%TOPIC%][OK]] %TMPL:P{"sep"}%
[[%TWIKIWEB%.TWikiRegistration][Register]] %TMPL:END%
%TMPL:P{"oops"}%
Suggest changing to:
%TMPL:INCLUDE{"oopsbase"}%

%TMPL:DEF{"message"}%

To edit topics on this %WIKITOOLNAME% collaborative web, you must be registered as a user.

---+++++ 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*.

---+++++ To register as a new user:

   * Simply fill out the *[[%TWIKIWEB%.TWikiRegistration][TWikiRegistration]]* form.
     It only takes a minute.%TMPL:END%
%TMPL:DEF{"topicaction"}%
[[%WEB%.%TOPIC%][OK]] %TMPL:P{"sep"}%
[[%TWIKIWEB%.TWikiRegistration][Register]] %TMPL:END%
%TMPL:P{"oops" titleaction="(oops)" action="*Attention*"
heading="Either you need to register or the authentication failed"}%
-- [[Main/JohnTalintyre]] - 24 Jul 2001
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
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
If I understand you correctly, you would like to have this change (in red) in `twiki.tmpl`:
%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;
%TMPL:P{"inhead"}% %TMPL:END%
Is that correct? Where would you define "inhead"? -- [[Main/PeterThoeny]] - 03 Aug 2001
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
-- [[MikeMannix]] - 30 Aug 2001