How A Skin Works

The main component of a skin is its template file. Pmwiki goes through (parses) the template and makes substitutions when it sees special layout markers (e.g. layout variables, also called skin directives).

The skin's template file is named either pub/skins/<skin-name>/<skin-name>.tmpl or pub/skins/<skin-name>/skin.tmpl where <skin-name> is all lower case with no spaces or hyphens. For example, a template file for "Foo Skin" would be pub/skins/foo/foo.tmpl. To have PmWiki use this skin, you'd add

Of course the "header stuff" and "HTML" may include all kinds of things that may change dynamically in many ways.

Often a skin also has at least one CSS stylesheet file and a PHP file. The PHP file must be named either skin.php or <the skin's folder name>.php, (e.g. foo.php for a skin in the pub/skins/foo/ directory). A documentation text file should also be included in a skin's folder. Example files for a Foo Skin:

Page Sections

Sections of output can be denoted using <!--Page...Fmt--> directives. The default sections? can be suppressed by special page directives in wiki markup, where an author can use (:notitle:), (:noheader:), etc. to turn off components of the page.

When a section is "turned off", output is suppressed from the <!--Page...Fmt--> until the next directive, a closing <!--/Page...Fmt--> or the end of the template is reached, whichever comes first.

A page section can also be turned off in a recipe or local configuration script using markup like

SetTmplDisplay('PageXyzFmt', 0);

that will suppress the <!--PageXyzFmt--> section of the template.

Since PmWiki 2 beta 22, you can make your own Page...Fmt sections. The reason you might want to do this is that you can then use the SetTmplDisplay() function in a skin.php or config.php to show or hide these sections, or you can create a (:noxyz:) directive so it can be controlled with wiki markup.

Note that SetTmplDisplay() expects each <!--PageMySectionFmt--> to have a unique name. If you need to hide or show a bunch of small items scattered about the page, you are best off using CSS classes and the property display:none.

Skin directives that denote page sections

These are provided by default:

<!--PageHeaderFmt-->

This is a convenient section to place a logo, a link to the homepage, anything you wish to place in the head of the pages. This section may be suppressed with the (:noheader:) directive.

<!--PageTitleFmt-->

This section is the standard section for placing the title and group links. This section may be suppressed with the (:notitle:) directive.

<!--PageActionFmt-->

This section is used for wiki action links. It may be suppressed with the (:noaction:) directive.

<!--PageLeftFmt-->

This section is customarily used for placing a SideBar menu, in the form of

<!--wiki:$Group.SideBar $SiteGroup.SideBar--> . This section may be suppressed with the (:noleft:) directive.

<!--PageRightFmt-->

This section would be used for right-side content. This section may be suppressed with the (:noright:) directive.

<!--PageFooterFmt-->

This section may hold footer content, often links to page actions and a "last-modified" line. This section may be suppressed with the (:nofooter:) directive.

Special skin directives

PmWiki includes special markers for inserting content from a wiki page, markup in the template, a PHP function, or a file on disk.

<!--wiki:pagename[ pagename ...]-->

This directive allows you to insert content from a wiki page. If multiple pages are specified, the first that exists will be used.

<!--markup:wiki-markups-->

This directive allows the skin author to insert wiki markup like (:searchbox:). Keep it all on one line; no line-breaks! Avoid leading spaces too; something like <!--markup: (:tag:)--> can get treated as monospace markup (<pre>...</pre>) the same as using leading whitespace in a wiki page.

<!--function:FunctionName args-->

This directive allows you to insert content generated by a PHP function.

The Page Title

Each HTML page requires a <title> tag. The content of it gets used in the heading of the results of search engines like Google. You may wish to include both the site title and the page title in your template.Here is a basic solution:

<title>$WikiTitle - $Titlespaced</title>

One problem with this is that any (:notitle:) directive will not suppress $Titlespaced or $Title used that way in the Head.Here is a solution which achieves that, by using a new variable in the template:

<title>$HTMLTitle</title>

Define the variable in the skin PHP file, and add a modified markup for the (:notitle:) directive:

Sample basic templates

If all these elements are in place the resulting skin will be fully functional, but rather bare to look at. Here is a bare-bone skin template, with just a minimum of styling so the SideBar appears beside the page content. This is a table-less template that uses absolute positioning of the sidebar to the left side and a margin in the body tag to shift all other elements to the right.

Translation

The text inside $[] brackets (e.g.$[Page History], $[Recent Changes], etc.) will be processed by PmWiki's internationalization feature (see PmWiki.Internationalizations), and replaced by the appropriate text from the current XLPage.

The main difference among these three is the order in which styles appear, which affects how skin styles take precedence compared to styles from the other sources. This is important because with CSS values assigned to attributes later will take precedence
over what was assigned earlier. The last wins.

A single-stylesheet approach

Using this method, which is preferred by some very experienced skin authors, a single stylesheet is loaded via a $HTMLHeaderFmt definition in skin.php:

The <link rel='stylesheet' ... /> line is omitted from the skin template
entirely.

Here a hierarchy is created where where the skin styles override the core PmWiki styles and recipe styles from local configuration files such as config.php. The wiki administrator can take final control over styling using local stylesheets (but not recipes).

Of course multiple stylesheets may be loaded this way also, allowing logic to determine which stylesheet links appear late in the <head> section of the page. The point is that using $HTMLHeaderFmt in skin.php to link a stylesheet causes the load order of styles to be

Two-stylesheet approach

The order of the two lines is very important. If they are reversed, the skin stylesheet link appears extremely late in the <head> section and the wiki administrator can't override the skin's styling. With the two lines in the correct order the load order of styles is

A skin author may, however, want to override the PmWiki defaults.The most reliable way to override the PmWiki defaults is to insert a second stylesheet using $HTMLHeaderFmt in skin.php, similar to the single-stylesheet method above.

Why pmwiki.php embeds CSS

The reason why pmwiki.php embeds the CSS is to
reduce the overhead on skin authors and to preserve an upgrade path.

The styles defined by $HTMLStylesFmt['pmwiki'] are really the
essential ones that are needed for several of PmWiki's core
markups. Without these in place, a number of PmWiki's built-in
features simply won't work.

In the past many have indicated that we should "dis-embed" the CSS
from pmwiki.php, and require every skin author to include these
minimal definitions (possibly modified) in the skin's .css file.
This slightly increases the work required to develop a skin,
because the skin author has to copy the definitions somewhere.
But more importantly, moving all of PmWiki's CSS properties into
the skins can make future PmWiki upgrades a bit of a pain, because
when a style definition is added or changed in the core, every
existing skin would then need to be modified to incorporate the
new minimal specification. I prefer to avoid that level of
coupling between core and skins.

The current approach allows skin CSS properties to be completely
decoupled from CSS properties needed for core and recipe markups.
In fact, in this sense pmwiki.php uses $HTMLStylesFmt[] in exactly
the same way that recipes do. $HTMLStylesFmt[] allows
module-specific CSS properties to be injected into the output
without the skin ever having to be aware of them, while preserving
the capability for skins and/or administrators to override the
module-specific properties if they wish to do so.

Replacing default CSS entirely

A skin that wants to completely replace the pmwiki.php defaults
with its own can do the following in skin.php:

The Preferences page tells PmWiki to use the custom Edit Form, but it could also be used for other translations as well. The preferences page would also be a good place to put translation strings that are specific to the skin.

JavaScript Tip

Note: This tip is slightly obsolete because it's now possible for form directives to specify "focus=1" as an option to indicate the control that should receive focus when the page is loaded.

"Favouring writers over readers": Putting the following code into the onload-handler (i.e. in window.onload = function(){ ... }) of the template gets the cursor focused on the first form element of the first form in the content area after the page is loaded, i.e. exactly where we want to have it (username field, edit field, etc.):

Notes

In references to skin.php above - skin can both be the literal 'skin' or the name of the skin in question, the latter takes precedence over the former. Chris Stiles

About <!--function:func param1 param2 ... : This will call the PHP function func with parameters param1, param2, ... and have the function's result inserted into the text. You can call any function that's defined by PHP, PmWiki, or an installed module/cookbook/skin recipe. (Warning: PmWiki functions may change name or functionality from release to release. Avoid calling them unless you have either foregone ever updating PmWiki, or asked in the mailing list whether using that function is OK. All functions might emit error messages if not called properly, most likely destroying your nice skin layout. You best bet is to write iron-clad functions in your skin.php that would degrade gracefully rather than let any error message out.)