Skin Templates

The framework used to render output

Overview

Skin Templates are plain text with embedded template directives and macros that are expanded by Foswiki to build an output, usually HTML.

Skin templates are used when composing the output from all actions, such as view, edit, and preview. By sharing common template definitions between all these actions, it makes it easy to change the look and feel of all pages by editing just a few templates.

Skin templates are either stored as text files with the extension .tmpl in the templates/ directory, or in Foswiki topics.

Template directives are expanded when the template is loaded, and are used to define the general structure of the output. Macros are expanded when the page is rendered, and fill in page-specific information.

See Macros for more information on macros.

How Template Directives Work

Template directives look a lot like standard Macros.
  • %TMPL:INCLUDE{"file"}% includes a template file. The file is found as described below.
  • %TMPL:DEF{"block"}% defines a block. All text between this and the next %TMPL:END% directive is removed and saved for later use with %TMPL:P%.
  • %TMPL:END% ends a block definition.
  • %TMPL:PREV%: returns the previous definition of the block being defined.
  • %TMPL:P{"var"}% includes a previously defined block.
  • %{...}% is a comment. Whitespace either side of the comment (newlines, spaces, tabs etc) is treated as part of the comment, and removed when the comment is removed.
You can use a block before or after declaring it. If you define the same block twice, only the second definition is used.

ALERT! Most template directives work only for templates: they do not get processed in normal topic text. The one exception is %TMPL:P.

Parameters to blocks

%TMPL:DEF% and %TMPL:P% support simple parameters. For example, given the definition %TMPL:DEF{"x"}% x%P%z%TMPL:END% then %TMPL:P{"x" P="y"}% will expand to xyz.

Parameters are only available in the immediate definition being included; they are not passed on to any other TMPL:P inside the TMPL:DEF being expanded unless they are passed on explicitly in a new parameter.

Any alphanumeric characters can be used in parameter names. TMPL:P parameters override any other possible definition of the name, so you should not use parameter names that might clash with Macros.

Conditional expansion

Three parameter names, context, then and else are reserved. They are used to support a limited form of "if" condition that you can use to select which of two TMPL:DEF to expand, based on a context identifier:
%TMPL:DEF{"link_inactive"}%<input type="button" disabled value="Link>%TMPL:END%
%TMPL:DEF{"link_active"}%<input type="button" onclick="link()" value="Link" />%TMPL:END%
%TMPL:P{context="inactive" then="link_inactive" else="link_active"}% for %CONTEXT%
When the inactive context is set, then this will expand the link_inactive TMPL:DEF; otherwise it will expand link_active.

This style of conditional expansion is used in preference to the %IF{} macro where possible because it is much more efficient.

See IfStatements for details of supported context identifiers.

%TMPL:INCLUDE recursion

You can use recursion with %TMPL:INCLUDE for piecewise customisation, or mixing in new features.

If there is a recursion in the %TMPL:INCLUDE chain (eg. view.tmpl contains %TMPL:INCLUDE{"view"}%), the templating system will detect that you are trying to include the same template again, and will instead include the next version of the template of that name that it finds in the template path.

For example, say you only want to override the breadcrumbs for the view script. You could create a tempate called view.crumbless.tmpl:
%TMPL:INCLUDE{"view"}%
%TMPL:DEF{"breadcrumb"}% We don't want any crumbs %TMPL:END%
and then * Set SKIN=crumbless,pattern

Comments

Comments %{...}% are removed from the templates as soon as the file is read, before any other template macros are evaluated. Whitespace either side of the comment (newlines, spaces, tabs etc) is also removed.

Finding Skin Templates

Most skin templates are stored in .tmpl files in the templates directory. For example, templates/view.tmpl is the default skin template file for the bin/view script. You can also save skin templates in user topics.

The {TemplatePath} configuration setting (in the Miscellaneous section of the configure page) defines which directories, files and Foswiki topics will be recognised as containing templates.

Skin templates that are loaded using %TMPL:INCLUDE with an explicit .tmpl extension are looked for only in the templates/ directory. For instance %TMPL:INCLUDE{"example.tmpl"}% will only return templates/example.tmpl, regardless of {TemplatePath} and SKIN settings.

All other templates are searched for using the {TemplatePath}. This is a list of generic name patterns, each of which contains the placeholders $name (the template name), $web (the web), and $skin (the skin), each standing in for part of the name. Each entry in this list is expanded in turn until the template is found.

The rules defined by the out-of-the-box setting of {TemplatePath} are:
  1. templates/$web/$name.$skin.tmpl
  2. templates/$name.$skin.tmpl
  3. $web.$skinSkin$nameTemplate
  4. System.$skinSkin$nameTemplate
  5. templates/$web/$name.tmpl
  6. templates/$name.tmpl
  7. $web.$nameTemplate
  8. System.$nameTemplate
For example, let's say we are viewing a topic in web Sandbox and are searching for the template called function. The skin path is set to custom,pattern. The following locations will be considered in turn, until a template is found:
  1. templates/Sandbox/function.custom.tmpl (rule 1) dead!
  2. templates/Sandbox/function.pattern.tmpl (rule 1) dead!
  3. templates/function.custom.tmpl (rule 2)
  4. templates/function.pattern.tmpl (rule 2)
  5. Sandbox.CustomSkinFunctionTemplate (rule 3)
  6. Sandbox.PatternSkinFunctionTemplate (rule 3)
  7. Projekte/Projekte/System.CustomSkinFunctionTemplate (rule 4)
  8. Projekte/Projekte/System.PatternSkinFunctionTemplate (rule 4)
  9. templates/Sandbox/function.tmpl (rule 5) dead!
  10. templates/function.tmpl (rule 6)
  11. Sandbox.FunctionTemplate (rule 7)
  12. Projekte/Projekte/System.FunctionTemplate (rule 8)
ALERT! dead! This usage is supported for compatibility only and is deprecated. Store web-specific templates in topics instead.

When a skin name or template name is used to build a topic name, the first character is automatically capitalised.

The skin path is set as described in Skins.

Template file names are usually derived from the name of the currently executing script; however it is also possible to override these settings in the view and edit scripts, for example when a topic-specific template is required. Two preference settings can be used to override the skin templates used:
  • VIEW_TEMPLATE sets the template to be used for viewing a topic.
  • EDIT_TEMPLATE sets the template for editing a topic.
If these preferences are set then the indicated templates will be chosen for view and edit respectively. The template search order remains as specified above.

Security and usability

Setting the {TemplatePath} is a compromise between the often opposing goals of security and usability. From a security perspective, allowing templates to be loaded from topics might open a door to people who want to inject their own evil HTML in those topics. From a usability perspective, it's very desireable to be able to override templates from topics, as it vastly increases the range of wiki applications.

The default {TemplatePath} comes down on the side of usability, by allowing templates from topics to be found before templates from the (more secure) templates directory. If you are particularly security concious, you may want to reverse this order, so that templates in templates/ are always found before those in topics. You can do this by simply moving rules 3 and 7 to the end of the list.

Note that topics containing templates are checked for VIEW access using the normal Foswiki access controls. Any access control failure is silently ignored, and the template path expansion continues.

Developing new templates

Debugging

When writing new templates, it can sometimes it can be hard to work out where different parts of the generated output come from. To help you debug your new templates, the Foswiki::Templates module has a "trace" mode. In this mode, the output is annotated with HTML comments that are wrapped around the output generated by each template, as it is expanded. For example, when trace mode is off,
%TMPL:DEF{"x:y"}% de %TMPL:END%
blah %TMPL:P{"x:y"}% blah
will expand to:
blah  de  blah
With tracing enabled, it will expand to:
blah <!--x:y--> de <!--/x:y--> blah
To enable the trace mode, edit lib/Foswiki/Templates.pm in your installation and change use constant TRACE => 0 to use constant TRACE => 1.

Note that the trace annotations may make your output look strange. However you can usually "view source" in the browser to see what was generated (or you may be able to run the script from the command-line e.g. cd bin; perl -T -I . view topic=MyWeb.MyTopic skin=mynewskin).

IDEA! Don't forget to switch the trace mode off again when you are finished!

Overview of the default templates

Finally, here's a very high-level overview of the default templates. These templates are rarely used on their own, but are used as the base on which skins, such as PatternSkin, are built.

foswiki.tmpl is the default master template. The main purpose of this template is to instantiate the following blocks:
  • htmldoctype - start of all HTML pages
  • bodystart - start of the body tag
  • main - page content
  • bodyend - end of the page
Default definitions are provided for each of these blocks. foswiki.tmpl is never used on its own, but is frequently included by other templates.

Next, there are a number of action-specific templates, such as view.tmpl, edit.tmpl, login.tmpl. These are the templates loaded by the actions of the same name. Their purpose is to include foswiki.tmpl, and provide new, page-specific, definitions of the blocks described above.

Several of the action-specific templates have skinned versions, such as view.print.tmpl and view.text.tmpl. These skinned versions are used to view the page in a specific way - for printing, or as plain text, for example.

messages.tmpl is an important template; it provides the basic definitions of all error and warning messages that Foswiki issues. These are defined using the %MAKETEXT macro to simplify translation into different languages.

attachtables.tmpl is another template worthy of separate mention. This template defines the different parts of the page that are involved in displaying tables of attachments. The blockes defined in this template are instantiated directly from code, rather than via %TMPL:P.

The remainder of the templates are used for varying purposes; their names, or introductory comments, should clarify.

A skin can provide a new version of any or all of these templates, depending on the depth of customisation. See the template files named *.pattern.* to see what PatternSkin defines.


Related Topics: Skins Macros JavascriptFiles
Topic revision: r2 - 14 Oct 2014, MatthiasGeorgi
 

This site is powered by FoswikiCopyright © by the contributing authors. All material on this site is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback