%META:TOPICINFO{author="ProjectContributor" comment="" date="1655468868" format="1.1" version="1"}%
%META:TOPICPARENT{name="Skins"}%
%STARTINCLUDE%
---+ Skin Templates

The framework used to render output.

%TOC%

%STARTSECTION{"PowerUserGuide"}%
---++ Overview

_Skin Templates_ are plain text with embedded _template directives_,
[[Macros][macros]] and [[SkinTemplateTokens][tokens]] that are expanded by
Foswiki to build an output page, usually HTML.

(If you are looking for the template used as 'starter text' for new topics.  see TemplateTopics.)

#HtmlTemplates
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_ and Template
_Tokens_ are expanded when the page is rendered, and fill in page-specific 
information.

Note that _Macros_ and _Tokens_ are written using the same syntax.  
See [[Macros]] for more information on macros.

_Tokens_ look exactly like Macros, but they are specific for the script
expanding the template, and cannot be used elsewhere in Foswiki.  See
[[SkinTemplateTokens]] for more information on tokens.

#TemplateMacros
---++ How Template Directives Work
Template directives look a lot like standard [[macros]].
   * =%<nop>TMPL:INCLUDE{"file"}%= includes a template file. The file is found as described [[#FindingTemplates][below]].
   * =%<nop>TMPL:DEF{"name"}%= defines a block. *All* text between this and the next =%<nop>TMPL:END%= directive is removed and saved for later use with =%<nop>TMPL:P%=.
   * =%<nop>TMPL:END%= ends a block definition.
   * =%<nop>TMPL:PREV%=: returns the previous definition of the block being defined.
   * =%<nop>TMPL:P{"name"}%= includes a previously defined block.
   * =%<nop>{...}%= 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.

<div class="foswikiHelp">
%X% Most template directives work only for templates: they do not get processed in normal topic text. The one exception is =%TMPL:P=.
</div>

---+++ Parameters to blocks
=%<nop>TMPL:DEF%= and =%<nop>TMPL:P%= support simple parameters.

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.


---++++ Block parameters
For example, we can define a parameter =P= inside a block:
<verbatim class="tml">
%TMPL:DEF{"x"}% x%P%z %TMPL:END%
</verbatim>
then pass a value to that parameter:
<verbatim class="tml">
%TMPL:P{"x" P="y"}%
</verbatim>
This will expand to =xyz=.

---++++ Block definition parameters
Default parameter values can be set in the definition:
<verbatim class="tml">
%TMPL:DEF{"x" y="1"}% x%y%z %TMPL:END%
</verbatim>
then
<verbatim class="tml">
%TMPL:P{"x"}%
</verbatim>
will expand to =x1z=.

You can also use a parameter inside a default parameter:
<verbatim class="tml">
%TMPL:DEF{"x" y="%value%"}% x%y%z %TMPL:END%
</verbatim>
then
<verbatim class="tml">
%TMPL:P{"x" value="1000"}%
</verbatim>
will expand to =x1000z=.


---++++ Naming
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
---++++ Using context identifiers
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_:
<verbatim class="tml">
%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%
</verbatim>
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
=[[VarIF][%<nop>IF{}]]= macro where possible because it is much more efficient.

See [[IfStatements#Context_identifiers][If Statements: Context identifiers]] for details of supported context identifiers.

---++++ Using parameters
The mechanism to pass parameters to blocks can be used to conditionally call different template blocks. For example:
<verbatim class="tml">
%TMPL:DEF{"conditional" tmpl="default"}%
%TMPL:P{"%tmpl%"}%
%TMPL:END%

%TMPL:DEF{"default"}%
This is a default template.
%TMPL:END%

%TMPL:DEF{"special"}%
This is a special template.
%TMPL:END%

...
%TMPL:P{"conditional" tmpl="special"}%
</verbatim>


---+++ =TMPL:INCLUDE= recursion
You can use recursion with =%<nop>TMPL:INCLUDE%= for piecewise customisation, or
mixing in new features.

If there is a recursion in the =%<nop>TMPL:INCLUDE%= chain (eg. =view.tmpl= contains
=%<nop>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
[[#TemplatePath][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=:
<verbatim class="tml">
%TMPL:INCLUDE{"view"}%
%TMPL:DEF{"breadcrumb"}% We don't want any crumbs %TMPL:END%
</verbatim>
and then =* Set SKIN=crumbless,pattern=

Remember: the template path contains the most specific template first.

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

#FindingTemplates
---++ 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 [[%SCRIPTURLPATH{configure}%][configure]] page) defines which directories,
files and Foswiki topics will be recognised as containing templates.

Skin templates that are loaded using =%<nop>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.

#TemplatePath
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 =%SYSTEMWEB%.$skinSkin$nameTemplate=
   5 =templates/$web/$name.tmpl=
   6 =templates/$name.tmpl=
   7 =$web.$nameTemplate=
   8 =%SYSTEMWEB%.$nameTemplate=
For example, let's say we are viewing a topic in web =%SANDBOXWEB%= 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/%SANDBOXWEB%/function.custom.tmpl= _(rule 1)_ :skull:
   1 =templates/%SANDBOXWEB%/function.pattern.tmpl= _(rule 1)_ :skull:
   2 =templates/function.custom.tmpl= _(rule 2)_
   2 =templates/function.pattern.tmpl= _(rule 2)_
   3 =%SANDBOXWEB%.CustomSkinFunctionTemplate= _(rule 3)_
   3 =%SANDBOXWEB%.PatternSkinFunctionTemplate= _(rule 3)_
   4 =%SYSTEMWEB%.CustomSkinFunctionTemplate= _(rule 4)_
   4 =%SYSTEMWEB%.PatternSkinFunctionTemplate= _(rule 4)_
   5 =templates/%SANDBOXWEB%/function.tmpl= _(rule 5)_ :skull:
   6 =templates/function.tmpl= _(rule 6)_
   7 =%SANDBOXWEB%.FunctionTemplate= _(rule 7)_
   8 =%SYSTEMWEB%.FunctionTemplate= _(rule 8)_
<div class="foswikiHelp">%X% :skull: This usage is supported *for compatibility only* and is *deprecated*. Store web-specific templates in topics instead. </div>

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

When a !SubWeb is used, the $web reference  must be qualified with a dot (.), not slash (/). For instance: If SANDBOXWEB above is a !SubWeb, then the reference must be <code>SANDBOXWEB = !Sandbox.SubWeb</code>. =Sandbox/SubWeb= does not work.

The _skin path_ is set as described in [[Skins]].

#TemplatePreferences
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 [[%SYSTEMWEB%.PreferenceSettings][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
   * locally (using _Local_ instead of _Set_) in a topic, or
   * in WebPreferences, or
   * in [[%LOCALSITEPREFS%]], or
   * in [[%SYSTEMWEB%.%WIKIPREFSTOPIC%]] (using _Set_),
then the indicated templates will be chosen for =view= and =edit= respectively. The template search order remains as specified above.

Note that the topic name specified as a template may need to be fully qualified with Web and !SubWeb. E.g.
<verbatim>
   * Set VIEW_TEMPLATE = Web.SubWeb.SpecificViewTemplate
</verbatim>
Also the qualification needs to be given in the form !Web.SubWeb.TopicTemplate as in the example; !Web/SubWeb.TopicTemplate or !Web/SubWeb/TopicTemplate does not work.

#TemplateSecurity
---+++ 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 [[AccessControl][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 HTML source created 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,
<verbatim class="tml">
%TMPL:DEF{"x:y"}% de %TMPL:END%
blah %TMPL:P{"x:y"}% blah
</verbatim>
will expand to:
<verbatim class="tml">
blah  de  blah
</verbatim>
With tracing enabled, the HTML source will look like:
<verbatim class="tml">
blah <!--x:y--> de <!--/x:y--> blah
</verbatim>
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=).

<div class="foswikiHelp">%I% Don't forget to switch the trace mode off again when you are finished!</div>

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

---++++ Template processing

The templates that render topic text are typically broken up into 3 areas,
divided by a token =%<nop>TEXT%=. 
<verbatim>
..header area before any topic text...
%TEXT%  (will be substituted with topic text)
...footer area after the topic text...
</verbatim>

When the core expands the template, it happens in 3 phases
   1 Macros are expanded and TML is rendered in the header area before the %<nop>TEXT% token, with context =header_text= set.
   1 The topic text then has its macros expanded, and TML rendered with context =body_text= set. The results replaces the %<nop>TEXT% token.
   1 Finally the footer area has it's macros expanded  and TML rendered in the area after the %<nop>TEXT% token with context =footer_text= set.

The contexts - =header_text=, =body_text= and =footer_text= are not used by the Foswiki core, but can be used by extensions during macro expansion to
determine which part  of the page is being processed.

---+++ Other important templates:

=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 =%<nop>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 blocks defined in this template are
instantiated directly from code, rather than via =%<nop>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.

%ENDSECTION{"PowerUserGuide"}%

---
*Related Topics:* [[Skins]] [[Macros]] [[JavascriptFiles]]

%STOPINCLUDE%
